树,二叉树的一些基础知识以及二叉树的建立,存储操作

来源:互联网 发布:浙江大学软件学院面试 编辑:程序博客网 时间:2024/05/18 23:55

首先,我们要明白,什么是树?这是大自然中一棵树的模型照片


而在数据结构中的树,会是什么样的结构呢?

树形结构广泛存在我们的现实生活里,下面两张图你一定不陌生吧,第一张是 Linux 文件系统结构,第二张是美国福特汽车公司的汽车家谱图。类似的树形结构还有很多,他们都可以抽象成数据结构里的树。和自然界里的树有所类似又有所不同,他们都有且仅有一个树根,树上的元素都是从树根衍生出来的。不同的是自然界里的树,它的树根在下面,而数据结构里的树,树根在上面。

树是由若干个有限结点组成的一个具有层次关系的集合,每棵树有且仅有一个,比如在图中,最上面的结点就是树的根结点。例子里的“/”、“etc”、“usr”、“lib”等等都是这棵树上的结点,其中“/”是树的根结点。

图中某个结点及其下面的所有结点并称为以该结点为根的子树,例如“usr”、“lib”、“bin”就是“/”的一棵子树,“usr”是该子树的根。结点拥有的子树个数我们称为结点的度,比如结点“/”的度为 7,“home”的度为 3。在例子中,我们称“usr”是“lib”、“bin”的父亲,“lib”、“bin”是“usr”的孩子。没有孩子的结点,也就是度为 0 的结点我们称为叶子,例如“etc”、“lib”、“bin”都是叶子结点。

我们规定根结点是树的第一层,树根的孩子结点是树的第二层,以此类推树的深度就是结点的最大层数,例如例子里的树,它的深度为 4。


下面我们用第二个例子简单复习下这几个概念,从图上,我们可以看到这是一棵以“美国福特汽车公司”为根结点,深度为 3 的树;“马自达”、“俊郎”是以“美国福特汽车公司”为根结点的一棵子树;“美国福特汽车公司”度为 8,“路虎”度为 0;“美国福特汽车公司”是“阿斯顿马丁”、“路虎”、“捷豹”等的父亲,“阿斯顿马丁”、“路虎”、“捷豹”是“美国福特汽车公司”的孩子;“路虎”、“野马”、“雷鸟”等都是树的叶子结点。


通过这两个例子的学习,我们可以发现树的一些性质:

1.每棵树有且仅有一个根结点;

2.在树上,从一个结点出发可以访问到其余的结点,并且一个结点到另一个结点的路径有且仅有一条;

3.父亲结点可以有多个孩子结点,除根结点外,其余的结点有且仅有一个父亲结点;

4.根结点没有父亲结点,叶子结点没有孩子结点。

而只有一个节点的树被称为平凡树(也叫平凡图),平凡树只有一个根节点。并且这个节点既是根节点也是叶子节点。

对于树,我们在数据结构中主要研究的的对象便是二叉树。

二叉树的概念:二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。

二叉树的每个结点至多只有两棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。

首先来了解一下两种特殊的二叉树:

第一个是满二叉树,如果一棵树深度为 k 而且有 2k - 1 个结点,那么我们称该二叉树为满二叉树,也就是说在此深度上,不能再添加结点了;第二个是完全二叉树如果一棵树深度为 k,从第 1 层到第 k - 1 层该树是满二叉树,第 k 层的结点都集中在左边,那么我们称该二叉树为完全二叉树。(解释:完全二叉树相当于是满二叉树从其最后一层的最右边开始删除节点,除最后一层外,每一层上的节点数均达到最大值;在最后一层上只缺少右边的若干结点完全二叉树因其结构的特殊性具有很高的效率,它经常被用在算法的优化里。

二叉树的创建:

#include<iostream>using namespace std;class Node{public:    int data;    Node *lchild,*rchild;  //分别指向Node节点的左孩子和右孩子    Node (int _data){       //构造函数,对新开辟的树的节点进行初始化处理        data = _data;           lchild = NULL;        rchild = NULL;    }};class BinaryTree{private:    Node *root;          //作为树根public:    BinaryTree (){        root = NULL;    //一开始初始化的时候,二叉树是一棵空树,root指向为空    }};int main() {    BinaryTree binarytree;    //声明一个类的对象实例    return 0;}

然后再我们创建完毕一棵二叉树之后,必然要将数据元素存储进二叉树,例如:

二叉树的建立方法有很多种,主要看建立二叉树的结构和规则。这里我们举个简单的例子,我们要建立如下图所示的一棵二叉树:根结点为 1,1 的左孩子是 2,右孩子是 3;2的左孩子是 4,右孩子是 5;3 没有左孩子,右孩子是 6;4、5、6 都是叶子结点。

树的结构:


#include<iostream>using namespace std;class Node {public:    int data;    Node *lchild, *rchild;    Node(int _data) {        data = _data;        lchild = NULL;        rchild = NULL;    }    ~Node() {           //析构函数,删除动态开辟的内存        if (lchild != NULL) {            delete lchild;        }        if (rchild != NULL) {               delete rchild;        }    }};class BinaryTree {private:    Node *root;public:    BinaryTree() {        root = NULL;    }    ~BinaryTree() {        if (root != NULL) {            delete root;    //析构函数,删除动态开辟的节点        }    }    void build_demo() {        //按照树的结构,存储树的节点        root = new Node(1);        root->lchild = new Node(2);        root->rchild = new Node(3);        root->lchild->lchild = new Node(4);        root->lchild->rchild = new Node(5);        root->rchild->rchild = new Node(6);    }};int main() {    BinaryTree binarytree;    binarytree.build_demo();    return 0;}

如有错误,还请指正,O(∩_∩)O谢谢








0 0