您的位置:首页 > 其它

二叉树(一)——二叉树的基本实现(数组实现和链表实现)

2014-08-05 16:14 561 查看
1.树是一种数据结构,树的一些相关的术语:

结点的度:一个结点的后继结点的个数。

树的度:树中度值最大的结点的度被称为树的度。

树的深度:树的层次数。

分支结点:度值大于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.二叉搜索树

若树中左子女的值都小于根节点的值,右子女的值都大于根节点的值,这样的二叉树叫做二叉搜索树。

AVL树本质上还是一棵二叉搜索树(因此读者可以看到我后面的代码是继承自二叉搜索树的),它的特点是:

(1) 本身首先是一棵二叉搜索树。

(2) 带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1。

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 = list[i];
current = root;
while(current != NULL)
{
parent = current;
if(current->data > p->data)
current = current->left;
else
current = current->right;
}
if(parent->data > p->data)
parent->left = p;
else
parent->right = p;
 }
}

int main()
{
int list[7] = {30, 18, 16, 25, 34, 7, 31};
ElemBT *root;

root = (ElemBT *)malloc(sizeof(ElemBT));
root->data = list[0];
root->left = root->right = NULL;
create_btree(root, list, 7);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐