首页 > 代码库 > 二叉树(一)——二叉树的基本实现(数组实现和链表实现)
二叉树(一)——二叉树的基本实现(数组实现和链表实现)
1.树是一种数据结构,树的一些相关的术语:
结点的度:一个结点的后继结点的个数。
树的度:树中度值最大的结点的度被称为树的度。
树的深度:树的层次数。
分支结点:度值大于0的结点,分支结点至少含有一个后继,分支结点也称为非终端结点。
叶子结点:树中的度值为0的结点。
双亲结点:树中某个结点的前驱结点,也成为父节点。
子女结点:树中某结点的后继结点。
兄弟结点:树中同一层的结点。
2.二叉树
(1)二叉树是一种特殊的树,树的度值最大为2.
(2)二叉树的表示:
A
/ \
B C
/ \ / \
D E F G
二元表示:
Binary-tree = (D, S)
(1)任何一棵二叉树的叶子结点总比双分支结点个数多一个。
分别设叶子结点,单分子结点,双分子结点的个数为:n0, n1, n2,则有:
n0+n1+n2 = 2n2+n1+1 ==> n0 = n2+1
2n2+n1+1:n2结点每个节点有两个叶子节点,n1结点每个结点有一个叶子结点,+1的原因是根结点不属于任何一个结点的子节点,所以根结点需要单独加上。
(2)二叉树的第i层最多有2^(i-1)个元素。
(3)一棵h层的二叉树最多有2^h - 1个元素。
4.满二叉树:h层的二叉树共有2^h - 1个元素。
完全二叉树:h层的二叉树若前h-1层是满的,最后一层是连续缺失右边的若干个结点。
对于完全二叉树存在:
(1)若结点编号为i的结点存在左子女,左子女编号为2i,若存在右子女,则右子女的结点编号为2i+1。
(2)编号为i的结点若存在双亲结点,则双亲结点的编号为i/2向下取整。
5.理想平衡二叉树:一棵h层的二叉树前h-1层是满的,最后一层的叶子结点可任意摆放。
二叉树存储的实现:
(1)顺序存储:将二叉树存储在内存中一块连续的存储单元中,数组的元素个数取决于二叉树的层数。
(2)将二叉树的每个结点的编号作为该结点在数组中的存储下标。
(3)将根节点存放在下标为1的单元里。
(4)若下标为i的单元存在左子女,则左子女的下标为2i,若存在右子女,右子女的下标为2i+1。
6.中根查找顺序
对于一个给定的二叉树,如果要对其进行遍历可以有前序遍历、中序遍历、后序遍历基本的三种遍历方式,这三种遍历方式都是相对于根而言的。比如中序遍历,就是先访问左子树,再访问根,最后访问右子树,意思就是根的访问顺序在中间。
对于一棵给定的二叉树:
中序遍历的顺序为:10, 42, 45, 55, 58, 63, 67, 70, 83, 90, 98。
从这个遍历顺序可以看出正好是一个从小到大的排过序的顺序,这是在构建二叉树的时候就可以做到的,在构建二叉树的时候,选择好根节点,比根节点小的数放到根节点的左子树,比根节点大的数放到根节点的右子树即可。
例如给出一个序列:63, 42, 45, 67, 70。
访问到63,将其作为根节点,访问到42<63则作为63的左子树,访问到45<63放到63的左子树上,而45>42所以放到42的右子树上,访问到67>63,则将67作为63的右子树,访问到70>63应该放在63的右子树上,而进一步有70>67,则70应该作为67的右子树,所以可以得到下面的二叉树:
63
/ \
42 67
\ \
45 70
7.二叉树的链式存储
结点类型:left域、data域、right域
left域:用来存放左子女的地址,若不存在左子女,left域为空。
data域:用来存放该结点的数据。
right域:用来存放右子女的地址,若不存在右子女,right域为空。
8.二叉搜索树
结点的度:一个结点的后继结点的个数。
树的度:树中度值最大的结点的度被称为树的度。
树的深度:树的层次数。
分支结点:度值大于0的结点,分支结点至少含有一个后继,分支结点也称为非终端结点。
叶子结点:树中的度值为0的结点。
双亲结点:树中某个结点的前驱结点,也成为父节点。
子女结点:树中某结点的后继结点。
兄弟结点:树中同一层的结点。
2.二叉树
(1)二叉树是一种特殊的树,树的度值最大为2.
(2)二叉树的表示:
A
/ \
B C
/ \ / \
D E F G
二元表示:
Binary-tree = (D, S)
D={A, B, C, D, E, F, G}
S={<A,B>, <A,C>, <B,D>, <B,E>, <C,F>, <C,G>}
3.二叉树的特点(1)任何一棵二叉树的叶子结点总比双分支结点个数多一个。
分别设叶子结点,单分子结点,双分子结点的个数为:n0, n1, n2,则有:
n0+n1+n2 = 2n2+n1+1 ==> n0 = n2+1
2n2+n1+1:n2结点每个节点有两个叶子节点,n1结点每个结点有一个叶子结点,+1的原因是根结点不属于任何一个结点的子节点,所以根结点需要单独加上。
(2)二叉树的第i层最多有2^(i-1)个元素。
(3)一棵h层的二叉树最多有2^h - 1个元素。
4.满二叉树:h层的二叉树共有2^h - 1个元素。
完全二叉树:h层的二叉树若前h-1层是满的,最后一层是连续缺失右边的若干个结点。
对于完全二叉树存在:
(1)若结点编号为i的结点存在左子女,左子女编号为2i,若存在右子女,则右子女的结点编号为2i+1。
(2)编号为i的结点若存在双亲结点,则双亲结点的编号为i/2向下取整。
5.理想平衡二叉树:一棵h层的二叉树前h-1层是满的,最后一层的叶子结点可任意摆放。
二叉树存储的实现:
(1)顺序存储:将二叉树存储在内存中一块连续的存储单元中,数组的元素个数取决于二叉树的层数。
(2)将二叉树的每个结点的编号作为该结点在数组中的存储下标。
(3)将根节点存放在下标为1的单元里。
(4)若下标为i的单元存在左子女,则左子女的下标为2i,若存在右子女,右子女的下标为2i+1。
6.中根查找顺序
对于一个给定的二叉树,如果要对其进行遍历可以有前序遍历、中序遍历、后序遍历基本的三种遍历方式,这三种遍历方式都是相对于根而言的。比如中序遍历,就是先访问左子树,再访问根,最后访问右子树,意思就是根的访问顺序在中间。
对于一棵给定的二叉树:
中序遍历的顺序为:10, 42, 45, 55, 58, 63, 67, 70, 83, 90, 98。
从这个遍历顺序可以看出正好是一个从小到大的排过序的顺序,这是在构建二叉树的时候就可以做到的,在构建二叉树的时候,选择好根节点,比根节点小的数放到根节点的左子树,比根节点大的数放到根节点的右子树即可。
例如给出一个序列:63, 42, 45, 67, 70。
访问到63,将其作为根节点,访问到42<63则作为63的左子树,访问到45<63放到63的左子树上,而45>42所以放到42的右子树上,访问到67>63,则将67作为63的右子树,访问到70>63应该放在63的右子树上,而进一步有70>67,则70应该作为67的右子树,所以可以得到下面的二叉树:
63
/ \
42 67
\ \
45 70
7.二叉树的链式存储
结点类型:left域、data域、right域
left域:用来存放左子女的地址,若不存在左子女,left域为空。
data域:用来存放该结点的数据。
right域:用来存放右子女的地址,若不存在右子女,right域为空。
8.二叉搜索树
若树中左子女的值都小于根节点的值,右子女的值都大于根节点的值,这样的二叉树叫做二叉搜索树。
9.二叉树的数组实现方式
分析:首先给定一个二叉树之后,就可以知道该二叉树的层次数h,然后创建一个2^h = 2^h - 1 + 1个元素的数组,加1的目的是因为数组的0下标是不用的,根节点存放在下标为1的单元中。所有数组中没有用到的单元,均赋值为二叉树中数值域不包含的值,这样在遍历的时候就可以将这个值作为判断的依据。
#include <stdio.h> void create_btree(int list[], int bt[], int n) /*n表示list数组中元素的个数*/ { int i, order; bt[1] = list[0]; for(i = 1; i < n; i++) { order = 1; /*每次进来从根结点开始比较*/ while(bt[order] != 0) { if(list[i] < bt[order]) order *= 2; else order = order*2 + 1; } bt[order] = list[i]; } } int main() { int list[7] = {30, 18, 16, 25, 34, 7, 31}; int bt[16] = {0}; int i; create_btree(list, bt, 7); for(i = 0; i < 16; i++) /*按层输出*/ if(bt[i] != 0) printf("%4d", bt[i]); printf("\n"); return 0; }程序的输出结果:
二叉树的链表实现:
#include <stdio.h> #include <malloc.h> #define NULL 0 typedef struct tree { int data; struct tree *left, *right; }ElemBT; void create_btree(ElemBT *root, int list[], int n) /*n表示list数组中元素的个数*/ { int i; ElemBT *current, *parent, *p; for(i = 1; i < n; i++) { p = (ElemBT *)malloc(sizeof(ElemBT)); p->left = p->right = NULL; p->data = http://www.mamicode.com/list[i];>
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。