二叉树的性质
一般二叉树性质:
- 在非空二叉树的k层上,至多有2k个节点(k>=0)
- 高度为k的二叉树中,最多有2k+1-1个节点(k>=0)
- 对于任何一棵非空的二叉树,如果叶节点个数为n0,度数为2的节点个数为n2,则有: n0 = n2 + 1
完全二叉树性质:
- 具有n个节点的完全二叉树的高度k为[log2n]
- 对于具有n个节点的完全二叉树,如果按照从上(根节点)到下(叶节点)和从左到右的顺序对二叉树中的所有节点从0开始到n-1进行编号,则对于任意的下标为k的节点,有:
- 如果k=0,则它是根节点,它没有父节点;如果k>0,则它的父节点的下标为[(i-1)/2];
- 如果2k+1 <= n-1,则下标为k的节点的左子结点的下标为2k+1;否则,下标为k的节点没有左子结点.
- 如果2k+2 <= n-1,则下标为k的节点的右子节点的下标为2k+2;否则,下标为k的节点没有右子节点
满二叉树性质:
在满二叉树中,叶节点的个数比分支节点的个数多1
扩充二叉树性质:
- 在扩充二叉树中,外部节点的个数比内部节点的个数多1
- 对任意扩充二叉树,外部路径长度E和内部路径长度I之间满足以下关系:E = I + 2n, 其中n是内部节点个数
二叉树的实现与周游
二叉树的顺序表示:
二叉树的顺序表示适用于完全二叉树,根据完全二叉树的第2性质,可以建立处节点之间的关系,对于一般的二叉树,可以将其扩充为完全二叉树,然后用一维数组顺序存储.
以下是程序代码:
bintree.h
1 #include<stdio.h>
2 #include<stdlib.h>
3 #define USED 1
4 #define NOTUSED 0
5 typedef int Type;
6
7 // 二叉树节点结构体
8 typedef struct treenode
9 {
10 int nodeIndex;
11 // 标志是否为外部节点,如果是则为0,否则为1
12 int isIn;
13 // 0表示这个节点不在二叉树中,1表示在树中
14 int isUsed;
15 Type element;
16 }TreeNode;
17
18 // 二叉树结构体
19 typedef struct bintree
20 {
21 int MAXN;
22 int n;
23 TreeNode *nodelist;
24 }*Tree;
25
26 // 创建最大节点为m的空二叉树
27 Tree createBinTree(int m)
28 {
29 int i;
30 Tree tree = NULL;
31 TreeNode *nodelist = NULL;
32 tree = malloc(sizeof(struct bintree));
33 if (NULL != tree)
34 {
35 nodelist = malloc(m * sizeof(TreeNode));
36 if (NULL != nodelist)
37 {
38 tree->MAXN = m;
39 tree->n = -1;
40 for (i = 0; i < m; i++)
41 {
42 nodelist[i].isUsed = NOTUSED;
43 nodelist[i].nodeIndex = i;
44 }
45 printf("\n");
46 tree->nodelist = nodelist;
47 }
48 }
49 return tree;
50 }
51
52 // 在二叉树末尾加入元素
53 void inTree(Tree tree, Type x, int isIn)
54 {
55 void replaceTree(Tree, Type, int, int);
56 if (tree->n + 1 < tree->MAXN)
57 {
58 replaceTree(tree, x, tree->n + 1, isIn);
59 tree->n = tree->n + 1;
60 }
61 return;
62 }
63
64 // 替换二叉树中指定下标的元素
65 void replaceTree(Tree tree, Type x, int index, int isIn)
66 {
67 if (tree->n == -1 || (index >= 0 && index <= tree->n + 1))
68 {
69 tree->nodelist[index].element = x;
70 tree->nodelist[index].isIn = isIn;
71 tree->nodelist[index].isUsed = USED;
72 }
73 return;
74 }
75
76 // 得到指定下标的元素
77 Type getNode(Tree tree, int index)
78 {
79 int re;
80 if (index >= 0 && index <= tree->n)
81 re = tree->nodelist[index].element;
82 return re;
83 }
84
85 // 得到父节点的元素下标
86 int parent(Tree tree, int child)
87 {
88 if (child < 0 || child > tree->n)
89 return -1;
90 else
91 return (child - 1) / 2;
92 }
93
94 // 得到右子节点的元素下标
95 int rightChild(Tree tree, int parent)
96 {
97 if (parent < 0 || parent > tree->n)
98 return -1;
99 else
100 return 2 * parent + 2;
101 }
102
103 // 得到左子节点的元素下标
104 int leftChild(Tree tree, int parent)
105 {
106 if (parent < 0 || parent > tree->n)
107 return -1;
108 else
109 return 2 * parent + 1;
110 }
这里用的是非递归的周游方法,所以要用到栈,一下是自定义的栈.
stack.h
1 #include "bintree.h"
2 typedef TreeNode DataType;
3
4 typedef struct mystack
5 {
6 //数组最大长度
7 int MAXN;
8 //指定栈顶位置
9 int index;
10 DataType *ele;
11
12 }*MyStack, Stack;
13
14
15 //创建一个空栈
16 MyStack createStack(int num)
17 {
18 MyStack stack = NULL;
19 stack = malloc(sizeof(Stack));
20 if(stack != NULL)
21 {
22 stack->ele = malloc(sizeof(DataType) * num);
23 if(stack ->ele != NULL)
24 {
25 stack ->MAXN = num;
26 stack ->index = -1;
27 }
28 }
29 return stack;
30 }
31
32 //判断栈是否为空
33 int isEmptyStack(MyStack stack)
34 {
35 return stack ->index == -1;
36 }
37
38 //元素入栈,如果栈已经满则返回0,否则返回1
39 int push(MyStack stack, DataType x)
40 {
41 int index = stack ->index + 1;
42 if(index >= stack ->MAXN)
43 return 0;
44 else
45 {
46 stack ->ele[index] = x;
47 stack ->index = index;
48 return 1;
49 }
50 }
51
52 //元素出栈,如果栈已经为空返回0,否则返回1
53 int pop(MyStack stack)
54 {
55 if(isEmptyStack(stack))
56 return 0;
57 else
58 {
59 stack ->index--;
60 return 1;
61 }
62 }
63
64 //取栈顶元素
65 DataType top(MyStack stack)
66 {
67 DataType get;
68 if(!isEmptyStack(stack))
69 get = stack ->ele[stack ->index];
70 return get;
71 }
bintree.c
1 #include "stack.h"
2
3 //访问节点信息
4 int visit(TreeNode node)
5 {
6 printf(" %d", node.element);
7 return node.nodeIndex;
8 }
9
10 //先根次序周游
11 void preOrder(Tree tree, MyStack stack)
12 {
13 int index = 0;
14 TreeNode node;
15 if(!tree->nodelist[index].isUsed)
16 return;
17 push(stack,tree->nodelist[index]);
18 while(!isEmptyStack(stack))
19 {
20 node = top(stack);
21 pop(stack);
22 if(node.isUsed == USED)
23 {
24 index = visit(node);
25 push(stack,tree->nodelist[rightChild(tree, index)]);
26 push(stack,tree->nodelist[leftChild(tree, index)]);
27 }
28
29 }
30 }
31
32 //中根次序周游
33 void inOrder(Tree tree, MyStack stack)
34 {
35 int index = 0;
36 TreeNode node;
37 if(tree->nodelist[index].isUsed == NOTUSED)
38 return;
39 do
40 {
41 while(tree->nodelist[index].isUsed == USED)
42 {
43 push(stack,tree->nodelist[index]);
44 index = leftChild(tree, index);
45 }
46 node = top(stack);
47 pop(stack);
48 index = visit(node);
49 index = rightChild(tree,index);
50 } while(tree->nodelist[index].isUsed == USED || !isEmptyStack(stack));
51
52 }
53
54 //后根次序周游
55 void postOrder(Tree tree, MyStack stack)
56 {
57 int index = 0, rightIndex;
58 TreeNode node;
59 if(tree->nodelist[index].isUsed == NOTUSED)
60 return;
61 while(tree->nodelist[index].isUsed == USED || !isEmptyStack(stack))
62 {
63 while(tree->nodelist[index].isUsed == USED)
64 {
65 push(stack,tree->nodelist[index]);
66 rightIndex = rightChild(tree, index);
67 index = leftChild(tree ,index);
68 if(tree->nodelist[index].isUsed == NOTUSED)
69 index = rightIndex;
70 }
71 node = top(stack);
72 pop(stack);
73 index = visit(node);
74 //如果栈不为空,且从左子树退回,进入到右子树遍历
75 if(!isEmptyStack(stack) && index == leftChild(tree,top(stack).nodeIndex))
76 index = rightChild(tree,top(stack).nodeIndex);
77 else tree->nodelist[index].isUsed = NOTUSED;
78 }
79
80 }
81
82 int main()
83 {
84 int m = 0, isIn = 1, j, buffer = 0;
85 Tree tree = NULL;
86 MyStack stack = NULL;
87
88 printf("请输入节点个数:");
89 scanf("%d",&m);
90 tree = createBinTree(m);
91 stack = createStack(m);
92 printf("请输入%d个数字:",m);
93 //将0到5六个元素依次放入二叉树中
94 for(j = 0; j < m; j++)
95 {
96 scanf(" %d", &buffer);
97 inTree(tree, buffer, isIn);
98 }
99
100 printf("先根次序周游结果为:");
101 preOrder(tree,stack);
102 printf("\n");
103
104 printf("中根次序周游结果为:");
105 inOrder(tree, stack);
106 printf("\n");
107
108 printf("后根次序周游结果为:");
109 postOrder(tree, stack);
110 printf("\n");
111
112 return 1;
113 }
按图示二叉树输出:
输出结果为:
二叉树连接表示:
1 #include<stdio.h>
2 #include<stdlib.h>
3 typedef int DataType;
4 typedef struct treenode *TreeNode;
5 typedef struct treenode *BinTree;
6
7 struct treenode
8 {
9 DataType element;
10 TreeNode llink;
11 TreeNode rlink;
12 };
13
14 BinTree createBinTree(DataType x)
15 {
16 BinTree tree = NULL;
17 tree = malloc(sizeof(struct treenode));
18 tree->element = x;
19 return tree;
20 }
21
22 BinTree addToLeft(BinTree t, DataType x)
23 {
24 TreeNode node = NULL;
25 node = malloc(sizeof(struct treenode));
26 if (node != NULL)
27 node->element = x;
28 t -> llink = node;
29 return node;
30 }
31
32 BinTree addToRight(BinTree t, DataType x)
33 {
34 TreeNode node = NULL;
35 node = malloc(sizeof(struct treenode));
36 if (node != NULL)
37 node->element = x;
38 t-> rlink = node;
39 return node;
40 }
41
42 void visitRoot(BinTree tree)
43 {
44 printf("%d ", tree->element);
45 }
46
47 BinTree leftChild(BinTree tree)
48 {
49 return tree->llink;
50 }
51
52 BinTree rightChild(BinTree tree)
53 {
54 return tree->rlink;
55 }
56 //用递归方法
57 //先根周游
58 void preOrder(BinTree tree)
59 {
60 if(tree == NULL)
61 return;
62 visitRoot(tree);
63 preOrder(leftChild(tree));
64 preOrder(rightChild(tree));
65 }
66
67 //中根周游
68 void inOrder(BinTree tree)
69 {
70 if(NULL == tree)
71 return;
72 inOrder(leftChild(tree));
73 visitRoot(tree);
74 inOrder(rightChild(tree));
75 }
76
77 //后根周游
78 void postOrder(BinTree tree)
79 {
80 if(NULL == tree)
81 return;
82 postOrder(leftChild(tree));
83 postOrder(rightChild(tree));
84 visitRoot(tree);
85 }
86
87 int main()
88 {
89 BinTree left, right;
90 BinTree tree = createBinTree(5);
91 left = addToLeft(tree, 4);
92 right = addToRight(tree, 3);
93 addToLeft(left, 8);
94 addToRight(left, 7);
95 addToLeft(right, 6);
96
97 printf("先根周游次序:");
98 preOrder(tree);
99 printf("\n");
100 printf("中根周游次序:");
101 inOrder(tree);
102 printf("\n");
103 printf("后根周游算法:");
104 postOrder(tree);
105 printf("\n");
106 return 1;
107 }
转载 http://www.cnblogs.com/hanyuan/archive/2012/05/10/bintree.html