二叉树的实现
发布日期:2021-05-28 18:23:14 浏览次数:13 分类:精选文章

本文共 6196 字,大约阅读时间需要 20 分钟。

为了更清晰地理解代码和二叉树操作的实现,我们将从节点类开始,逐步分析各个功能的实现细节。下面将详细解释TNode类和IThree类的实现,并结合测试案例来验证代码的正确性。

1. 节点类TNode的实现

TNode类定义了一个二叉树的节点,包含三个主要字段:

  • date:存储节点的值。
  • leftChild:左子节点。
  • rightChild:右子节点。

类中含有一个构造函数,接收一个key作为初始化节点的值,其他两个字段初始化为null

public class TNode {    public int date;    public TNode leftChild;    public TNode rightChild;    public TNode(int key) {        this.date = key;    }}

2. 二叉树操作类IThree的实现

IThree类主要用于对二叉树进行各种操作,包括查找、插入、删除等功能。

  • 查找方法find(key)

该方法通过遍历树,比较节点的值来定位目标节点。每次比较都使用位运算优化判断方向。

TNode find(int key) {    TNode temp = root;    while (temp != null) {        if (key > temp.date) {            temp = temp.rightChild;        } else if (key < temp.date) {            temp = temp.leftChild;        } else {            return temp;        }    }    return null;}
  • 插入方法insert(key)

在插入前检查根是否为null,否则从根节点开始遍历,找到合适的位置,并将新节点插入,返回布尔值表示插入成功。

boolean insert(int key) {    TNode newNode = new TNode(key);    if (root == null) {        root = newNode;        return true;    }    TNode preNode = null;    TNode temp = root;    while (temp != null) {        preNode = temp;        if (key > temp.date) {            temp = temp.rightChild;            if (temp == null) {                preNode.rightChild = newNode;                return true;            }        } else {            temp = temp.leftChild;            if (temp == null) {                preNode.leftChild = newNode;                return true;            }        }    }    return false;}
  • 遍历方法(先序、中序、后序)

在这些方法中,分别按照先序、分序和后序的顺序对树进行遍历。每个方法都递归地访问左子节点后再访问右子节点。

void infixOrder(TNode current) {    if (current != null) {        System.out.print(current.date + "    ");        infixOrder(current.leftChild);        infixOrder(current.rightChild);    }}void preOrder(TNode current) {    if (current != null) {        preOrder(current.leftChild);        System.out.print(current.date + "    ");        preOrder(current.rightChild);    }}void postOrder(TNode current) {    if (current != null) {        postOrder(current.leftChild);        postOrder(current.rightChild);        System.out.print(current.date + "    ");    }}
  • 查找最值方法findMax()和findMin()

这两种方法分别找到树中的最大值和最小值。findMax()从根节点的右子节点开始遍历,直到找到最大的节点;findMin()则从根节点的左子节点开始,找到最小的节点。

TNode findMax() {    TNode preNode = null;    TNode temp = root;    if (root != null) {        while (temp != null) {            preNode = temp;            temp = temp.rightChild;        }    }    return preNode;}TNode findMin() {    TNode preNode = null;    TNode temp = root;    if (root != null) {        while (temp != null) {            preNode = temp;            temp = temp.leftChild;        }    }    return preNode;}
  • 删除方法delete(key)

删除操作比较复杂,需要处理三种情况。该方法采用非递归的方式查找节点,并根据节点情况调整子节点的指针。

boolean delete(int key) {    TNode preNode = root;    TNode nextNode = root;    while (nextNode.date != key) {        preNode = nextNode;        if (key < nextNode.date) {            nextNode = nextNode.leftChild;        } else {            nextNode = nextNode.rightChild;        }        if (nextNode == null) {            return false;        }    }    // 该节点已找到    if (nextNode.leftChild == null && nextNode.rightChild == null) {        // 该节点为叶子节点        if (nextNode == root) {            root = null;        } else if (preNode.leftChild == nextNode) {            preNode.leftChild = null;        } else {            preNode.rightChild = null;        }        return true;    } else if (nextNode.leftChild == null && nextNode.rightChild != null) {        // 该节点只有右孩子        if (nextNode == root) {            root = nextNode.rightChild;        }        if (preNode.rightChild == nextNode) {            preNode.rightChild = nextNode.rightChild;        } else {            preNode.leftChild = nextNode.rightChild;        }        return true;    } else if (nextNode.leftChild != null && nextNode.rightChild == null) {        // 该节点只有左孩子        if (nextNode == root) {            root = nextNode.leftChild;        }        if (preNode.rightChild == nextNode) {            preNode.rightChild = nextNode.leftChild;        } else {            preNode.leftChild = nextNode.leftChild;        }        return true;    } else {        // 该节点有两个子节点        TNode successor = getSuccessor(nextNode);        if (nextNode == root) {            root = successor;        }        if (preNode.leftChild == nextNode) {            preNode.leftChild = successor;        } else {            preNode.rightChild = successor;        }        successor.leftChild = nextNode.leftChild;        return true;    }}
  • 找到删除节点的后继方法getSuccessor(delNode)

该方法用于在删除节点时找到其中序后继节点,将右边的结构调整到左边,以保持树的平衡。

TNode getSuccessor(TNode delNode) {    TNode successorParent = delNode;    TNode successor = delNode;    TNode current = delNode.rightChild;    while (current != null) {        successorParent = successor;        successor = current;        current = current.leftChild;    }    if (successor != delNode.rightChild) {        successorParent.leftChild = successor.rightChild;        successor.rightChild = delNode.rightChild;    }    return successor;}

3. 测试案例

main方法中,进行了一系列插入操作后,验证了各个功能的正确性:

public static void main(String[] args) {    IThree th = new IThree();    th.insert(4);    th.insert(2);    th.insert(1);    th.insert(3);    th.insert(6);    th.insert(5);    th.insert(7);    th.insert(8);    th.insert(0);    System.out.println(th.find(3).date);    System.out.println("先序遍历:");    th.infixOrder(th.root);    System.out.println();    System.out.println("中序遍历:");    th.preOrder(th.root);    System.out.println();    System.out.println("后序遍历:");    th.postOrder(th.root);    System.out.println();    System.out.println("最大值:" + th.findMax().date);    System.out.println("最小值:" + th.findMin().date);    System.out.println(th.delete(6));    System.out.println("中序遍历:");    th.preOrder(th.root);    System.out.println();}

4. 性能优化与注意事项

  • 删除优化:确保在删除节点有两个子节点时,将右子节点接到左子节点上,以保持树的平衡,这可以在后续操作中提高查找效率。
  • 遍历方法:每次递归之前检查节点是否为null,避免递归深度过大带来的栈溢出问题。
  • 插入优化:可以考虑引入循环插入技术,减少递归调用带来的开销,但目前的递归方式也能满足典型应用需求。

5. 总结与展望

通过上述详细分析,可以清晰地理解TNode类和IThree类的实现原理。尤其是删除操作,其对树结构的调整需要特别注意。这套实现能够成功地进行查找和插入操作,同时在删除操作中也考虑了树的平衡问题。未来的优化方向可以包括:

  • 引入动态布尔逻辑优化,以减少判断语句带来的性能消耗。
  • 引入自平衡插入技术,确保树的高度最小化,提高查找效率。
  • 考虑内存和磁盘中的大数据量处理,实现高效的 Serialization 和 Deserialization 接口。

这些改进将进一步提升代码的性能和可维护性,适用于更复杂和大规模的二叉树应用场景。

上一篇:(一)Java的类加载机制
下一篇:(六)剑指offer 二叉树篇

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2025年05月05日 02时14分16秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章