数据结构基础(16) --树与二叉树

树的基本术语

1.结点:{数据元素+若干指向子树的分支}

2.结点的度:分支的个数(子树的个数)

3.树的度:树中所有结点的度的最大值

4.叶子结点:度为零的结点

5.分支结点:度大于零的结点(包含根和中间结点)

6.(从根到结点的)路径:由从根到该结点所经分支和结点构成;

7.结点的层次:假设根结点的层次为1,则根的孩子为第2层,如果某节点在第L层,则其子树的根在L+1层。

8.树的深度:树中叶子结点所在的最大层次;

二叉树

二叉树或为空树,或是由一个根结点加上两棵分别称为左子树和右子树的、互不交的二叉树组成。(树的度最大为2)

二叉树的重要性质:

性质1:在二叉树的第i层上至多有2^(i-1)个结点(i≥1);

性质2:深度为 k 的二叉树上至多含 (2^k)-1个结点(k≥1);

性质3:对任何一棵二叉树,若它含有n0 个叶子结点(0度结点)、n2 个度为 2的结点,则必存在关系式:n0 = n2+1。

两类特殊的二叉树:

满二叉树:指的是深度为k且含有(2^k)-1个结点的二叉树。

完全二叉树:树中所含的 n 个结点和满二叉树中编号为 1 至 n 的结点一一对应。(编号的规则为,由上到下,从左到右。如上图所示)

完全二叉树的特点:

1.叶子节点出现在最后2层

2.对于任意结点,若其右分支下的子孙的最大层次为L,则左分支下的子孙的最大层次为L或L+1;

性质4:具有n个结点的完全二叉树的深度为[logn](向下取整)+1。

性质5:若对含 n 个结点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为 i 的结点:

(1) 若 i=1,则该结点是二叉树的根,无双亲,否则,编号为 [i/2](向下取整)的结点为其双亲结点;
(2) 若 2i>n,则该结点无左孩子,否则,编号为 2i 的结点为其左孩子结点;
(3) 若 2i+1>n,则该结点无右孩子结点,否则,编号为2i+1 的结点为其右孩子结点。

二叉树的链式存储实现

说明:

由于这篇博客仅仅是为了演示二叉树的理论, 因此代码所做的封装性以及可用性都不理想, 但由于在实际应用中, 也基本上不可能这样直接的使用二叉树, 因此也就没怎么优化他, 在此首先给大家说声抱歉;

二叉树节点构造

template <typename Type>
class TreeNode
{
    friend class BinaryTree<Type>;
//因为此处仅仅是为了演示, 因此将之定义为public
public:
    TreeNode(const Type &_data = Type(), TreeNode *_left = NULL, TreeNode *_right = NULL)
        : data(_data), leftChild(_left), rightChild(_right) { }

    Type data;
    TreeNode *leftChild;
    TreeNode *rightChild;
};

二叉树构造:

template <typename Type>
class BinaryTree
{
public:
    //二叉树可以进行的操作
    BinaryTree():root(NULL) {}
    bool isEmpty() const
    {
        return root == NULL;
    }
    //先序遍历
    void preOrder() const
    {
        return preOrder(root);
    }
    //中序遍历
    void inOrder() const
    {
        return inOrder(root);
    }
    //后续遍历
    void postOrder() const
    {
        return postOrder(root);
    }
    //层次遍历
    void levelOrder() const;

private:
    void preOrder(const TreeNode<Type> *rootNode) const;
    void inOrder(const TreeNode<Type> *rootNode) const;
    void postOrder(const TreeNode<Type> *rootNode) const;
    void visit(const TreeNode<Type> *node) const;

//因为此处仅仅是为了演示, 因此将之定义为public
public:
    TreeNode<Type> *root;
};

先(根)序的遍历算法:

1.若二叉树为空,则直接返回;

2.否则

(1)访问根结点(visit);

(2)先序遍历左子树;

(3)先序遍历右子树;

//实现
template <typename Type>
void BinaryTree<Type>::preOrder(const TreeNode<Type> *subTree) const
{
    if (subTree != NULL)
    {
        visit(subTree);

        preOrder(subTree->leftChild);
        preOrder(subTree->rightChild);
    }
}

中(根)序的遍历算法:

1.若二叉树为空树,则空操作;

2.否则

(1)中序遍历左子树;

(2)访问根结点;

(3)中序遍历右子树。

//实现
template <typename Type>
void BinaryTree<Type>::inOrder(const TreeNode<Type> *subTree)const
{
    if (subTree != NULL)
    {
        inOrder(subTree->leftChild);
        visit(subTree);
        inOrder(subTree->rightChild);
    }
}

后(根)序的遍历算法:

1.若二叉树为空树,则空操作;

2.否则

(1)后序遍历左子树;

(2)后序遍历右子树;

(3)访问根结点。

//实现
template <typename Type>
void BinaryTree<Type>::postOrder(const TreeNode<Type> *subTree)const
{
    if (subTree != NULL)
    {
        postOrder(subTree->leftChild);
        postOrder(subTree->rightChild);
        visit(subTree);
    }
}

层次遍历算法与visit操作:

template <typename Type>
void BinaryTree<Type>::levelOrder() const
{
    std::queue< TreeNode<Type>* > queue;
    queue.push(root);

    while (!queue.empty())
    {
        TreeNode<Type> *currentNode = queue.front();
        queue.pop();

        visit(currentNode);
        if (currentNode->leftChild != NULL)
            queue.push(currentNode->leftChild);
        if (currentNode->rightChild != NULL)
            queue.push(currentNode->rightChild);
    }
}
template <typename Type>
void BinaryTree<Type>::visit(const TreeNode<Type> *currentNode) const
{
    cout << currentNode->data << ‘ ‘;
}

二叉树构造与运用示例

构造一颗如下的二叉树:

//代码如下
int main()
{
    BinaryTree<char> tree;
    TreeNode<char> addition(‘+‘), subtraction(‘-‘), multiplies(‘*‘), divides(‘/‘);
    TreeNode<char> a(‘A‘), b(‘B‘), c(‘C‘), d(‘D‘), e(‘E‘);

    tree.root = &addition;
    addition.leftChild = &subtraction;
    addition.rightChild = &e;
    subtraction.leftChild = &multiplies;
    subtraction.rightChild = &d;
    multiplies.leftChild = ÷s;
    multiplies.rightChild = &c;
    divides.leftChild = &a;
    divides.rightChild = &b;

    cout << "preOrder: ";
    tree.preOrder();
    cout << endl;
    cout << "inOrder: " ;
    tree.inOrder();
    cout << endl;
    cout << "postOrder: ";
    tree.postOrder();
    cout << endl;

    cout << "level Order";
    tree.levelOrder();
    cout << endl;

    return 0;
}

遍历算法的应用举例

1.统计二叉树中叶子结点的个数(先序遍历)

2.求二叉树的深度(后序遍历)

3.复制二叉树(后序遍历)

时间: 2024-10-11 12:43:40

数据结构基础(16) --树与二叉树的相关文章

数据结构和算法 (二)数据结构基础之树、二叉树

Java面试宝典之二叉树的实现 我们接着上一篇数据结构继续讲解.本章系数据结构之树与二叉树,从这章开始,我们就要介绍非线性结构了,这些内容理解起来比线性表稍难一些,我尽量写的通俗一些,如果读的过程中有任何问题,请按上述方式联系我! 一.树 树 形结构是一类重要的非线性结构.树形结构是结点之间有分支,并具有层次关系的结构.它非常类似于自然界中的树.树结构在客观世界中是大量存在的,例如家 谱.行政组织机构都可用树形象地表示.树在计算机领域中也有着广泛的应用,例如在编译程序中,用树来表示源程序的语法结

数据结构实践项目——树和二叉树(1)

本文针对[数据结构基础系列(6):树和二叉树]第1-10课时 1 树结构导学 2 树的基本概念 3 树的基本术语 4 树的性质 5 树的存储结构 6 二叉树概念和性质 7 二叉树与树.森林之间的转换 8 二叉树的存储结构 9 二叉树的基本运算及其实现 10 二叉树的遍历 [项目1 - 二叉树算法库] 定义二叉树的链式存储结构,实现其基本运算,并完成测试. 要求: 1.头文件btree.h中定义数据结构并声明用于完成基本运算的函数.对应基本运算的函数包括: void CreateBTNode(BT

数据结构实践项目——树和二叉树(2)

本文针对数据结构基础系列(6):树和二叉树第7, 11-15课时 7 二叉树与树.森林之间的转换 11 二叉树遍历非递归算法 12 层次遍历算法 13 二叉树的构造 14 线索二叉树 15 哈夫曼树 [项目1 - 二叉树算法验证] 运行并重复测试教学内容中涉及的算法.改变测试数据进行重复测试的意义在于,可以从更多角度体会算法,以达到逐渐掌握算法的程度.使用你的测试数据,并展示测试结果,观察运行结果,以此来领会算法. (1)层次遍历算法的验证 [参考链接] (2)二叉树构造算法的验证 [参考链接]

基本数据结构学习笔记——树与二叉树

1.树的形式化定义: 树(Tree)是由一个或多个结点组成的有限集合T,其中有一个特定的称为根的结点:其余结点可分为m(m≥0)个互不相交的有限集T1,T2,T3 ,…,Tm,每一个集合本身又是一棵树,且称为根的子树. 2.有关树的基本术语: 1.结点(Node):树中的元素,包含数据项及若干指向其子树的分支. 2.结点的度(Degree):结点拥有的子树数. 3.结点的层次:从根结点开始算起,根为第一层. 4.叶子(Leaf):度为零的结点,也称端结点. 5.孩子(Child):结点子树的根称

数据结构与算法分析-树、二叉树、二叉查找树

作者:xiabodan 出处:http://blog.csdn.net/xiabodan 二叉树 二叉树的申明: struct node { int data; struct node *left; struct node *right; }; 新建一个节点 /* newNode() allocates a new node with the given data and NULL left and right pointers. */ struct node* newNode(int data

算法与数据结构基础4:C++二叉树实现及遍历方法大全

binary search tree,中文翻译为二叉搜索树.二叉查找树或者二叉排序树.简称为BST. 本文集齐了二叉树的五大遍历算法:先序遍历.中序遍历.后序遍历.深度优先遍历和广度优先遍历(同层遍历也就是深度优先遍历). // BSTree.h #include <cstdio> #include <iostream> #include <stack> #include <queue> using namespace std; // binary sear

算法与数据结构基础11:C++实现——二拆搜索树节点删除

基于我的另一篇文章<算法与数据结构基础4:C++二叉树实现及遍历方法大全> ,二叉树的结构用的这篇文章里的. 二查找叉树的删除可以细分为三种情况: 1 被删除的是叶子节点,直接删除: 2 被删除只有一个子节点,指针下移: 3 有两个子节点,为了不破坏树的结构,需要找出一个节点来替换当前节点. 根据二叉树的特点,当前节点大于所有左子树,小于所有右子树, 可以用左子树中最大的节点,或者右子树最小的节点来替换当前节点,然后删除替换节点. // BSTree.h #include <cstdio

3、非线性结构--树与二叉树——数据结构【基础篇】

非线性结构--树与二叉树 二叉树的基础知识: 二叉树的特点: 1.每个结点的度<=2 2.二叉树是有序树 二叉树的五种不同的形态: 1.空树 2.一个根结点的根树 3.左子树 4.右子树 5.左右并存的二叉树 二叉树的性质: 性质1:二叉树第i层上的结点数目最多为 2{i-1} (i≥1) 性质2:深度为k的二叉树至多有2{k}-1个结点(k≥1) 性质3:包含n个结点的二叉树的高度至少为log2 (n+1) 性质4:在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2

数据结构基础温故-4.树与二叉树(上)

前面所讨论的线性表元素之间都是一对一的关系,今天我们所看到的结构各元素之间却是一对多的关系.树在计算机中有着广泛的应用,甚至在计算机的日常使用中,也可以看到树形结构的身影,如下图所示的Windows资源管理器和应用程序的菜单都属于树形结构.树形结构是一种典型的非线性结构,除了用于表示相邻关系外,还可以表示层次关系.本文重点讨论树与二叉树的基本结构和遍历算法等内容. 一.好大一棵树,绿色的祝福 1.1 树的基本概念 Defination:树(Tree)是 n(n≥0)个结点的有限集.n=0时,该树