数据结构 树.docx
- 文档编号:17693060
- 上传时间:2023-04-24
- 格式:DOCX
- 页数:22
- 大小:83.14KB
数据结构 树.docx
《数据结构 树.docx》由会员分享,可在线阅读,更多相关《数据结构 树.docx(22页珍藏版)》请在冰豆网上搜索。
数据结构树
树
分类:
Datastructure&C2012-03-0513:
5524人阅读评论(0)收藏举报
理论基础
递归不要太想细节,想大方向比较好.(树这多想递归)
树一般是有向↓(从根到叶子)无序←→
线形结构
树形结构
第一个元素无前驱
根无前驱
最后一个元素无后继
多个叶子结点无后继
其他元素一个前驱一个后继
其他结点一个前驱多个后继
树是从家族的族谱来的,(双亲,儿子)
定义:
根和子树,子树之间互不相交.(递归定义)树=(根,子树)
基本概念:
树的结点:
包含一个数据元素及若干指向其子树的分支。
结点的度:
结点拥有的子树(直接)数
叶子:
度为0(也叫终端结点)
分支结点:
度不为0(也叫非终端结点)(根除外)
树的度:
树内各个结点的度的最大值
结点的子树的根称为该结点的孩子,该结点成为孩子的双亲,同一个双亲的孩子之间互称兄弟
结点的祖先是从根到该结点所经分支上的所有结点,以某结点为根的子树中的任一结点都称为该结点的子孙
结点的层次:
从根开始定义起,根为第一层,根的孩子为第二层,依此类推
双亲在同一层的结点互为堂兄弟
树中结点的最大层次称为树的深度
树中结点的各个子树看成是从左到右有次序的,成为有序树,否则为无序树(一般都是无序树)
森林是m(m>=0)棵互不相交的书的集合
树的存储方式:
1.双亲表示
typedefstructPTNode{
ElemTYpedata;/*存储数据*/
intparent;/*在数组中的位序*/
}PT;
整个树的结构是以上结点的集合:
typedefstruct{
PTNodenodes[MAX_TREE_SIZE];
intr,n;/*根结点所在位置,结点个数*/
}PTree;/*双亲表示法*/
(n实际为7,图上一点点错误)
2.孩子链表
孩子结点结构
typedefstructCTNode{
intchild;
structCTNode*next;
}*ChildPtr;
双亲节点结构
typedefstructCTBox{
ElemTypedata;
ChildPtrfirstChild;/*第一个孩子的指针,之后顺序向后找到所有的孩子*/
};
整个树的结构是双亲节点的集合
typedefstruct{
CTBoxnodes[Max_node_size];
intn,r;/*n结点数和根的位置*/
}CTree;
(n=7)
3.孩子兄弟链表(可以实现树的操作转换为二叉树)
typedefstructCSNode{
ElemTypedata;
structCSNode*filrstchild,*nextsibling;/*左孩子,右兄弟*/
}CSNode,*CSTree;
森林和二叉树的对应转换关系:
(递归)
设森林F=(T1,T2,T......)(除T1外,其余的为最后二叉树的右子树)
T1=(root,t11,t12,...)其中root为T1这棵子树的根,其余的为子树森林(root为最后二叉树的根,子树为最后二叉树的左子树)
二叉树B=(LBT,Node(root),RBT);
二叉树转变为森林:
(递归,上边倒过来了)
由Node(root)对应得到ROOT(T1)二叉树的根变成森林第一棵树的根
由LBT得到(t1,t2,t...)二叉树的左子树变成第一棵树的子树森林
由RBT得到(T2,T3,T...)二叉树的右子树得到其他子树
树和森林的遍历:
树的遍历:
1.先序遍历(根,第一子树,其他子树)
2.后序遍历(左孩子-》第一棵子树,其他子树,根)
3.按照层次
树的先根遍历对应森林的先序遍历对应二叉树的先序遍历
树的后根遍历对应森林的中序遍历对应二叉树的中序遍历
森林遍历:
1.先序遍历(根,第一子树森林,其他子树)
2.中序遍历(左孩子-》第一棵子树森林,根,其他子树)
3.按照层次
二叉树:
每个结点至多只有两棵子树(二叉树中不存在度大于2的结点),二叉树的子树有左右之分,其次序不能任意颠倒.(有序树)
二叉树的5种状态:
空二叉书,仅有根结点的二叉树,右子树为空的二叉树,左,右子树非空的二叉树,左子树为空的二叉树
二叉树的性质:
a.在二叉树的第i层上至多有2i–1个结点(i>=1)
b.深度为k的二叉树至多有2k-1个结点(k>=1)
c.对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2则n0=n2+1
满二叉树:
深度为k且有2k–1个结点(除叶子结点,全都是度为2的结点),编号的满二叉树为完全二叉书(编号顺序↓→)
完全二叉树的特性:
a.具有n个结点的完全二叉树的深度为log2n+1(log2n向下取整).
b.完全二叉树按层次编号i层
如果i=1则为二叉树的根,无双亲,否则双亲为i/2.
如果2i>n(结点总数),则结点i无左孩子(结点i为叶子结点)否则左孩子为2i
如果2i+1>n,则结点i无右孩子,否则右孩子为2i+1
二叉树的存储结构
1.顺序存储结构(参照完全二叉树存储,参照完全二叉树的编号)
#defineMAX_TREE_SIZE100
typedefTElemTypeSqBiTree[MAX_TREE_SIZE];
SqBiTreebt;
例如:
a
b
c
d
e
0
0
0
0
f
g
如上:
顺序存储会浪费很多空间(除非是完全二叉树),所以不推荐使用
2.链式存储结构(二叉链表,三叉链表)
二叉链表:
lchild-data-rchild(结点包含三个域)
三叉链表:
lchild-data-parent-rchild(结点包含四个域)
链表的头指针指向二叉树的根结点
定义:
typedefstructBiTNode{
TElemTypedata;//例如char型
structBiTNode*lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;//二叉链表
遍历二叉树:
需要找到一种规律,使二叉树上的结点排列在一个线性队列上,从而便于遍历
先序遍历:
根左右
中序遍历:
左根右
后序遍历:
左右根
表达式求值中的:
逆波兰式(先序,中序,后序)正好对应.
二叉链表基本操作:
[cpp]viewplaincopyprint?
1/*TheBasicoperatefor二叉树,采用二叉链表存储方式
2*Author:
Kevin
3*Date:
2012.03.06
4*树这会用到很多递归
5**/
6
7
8#include"stdio.h"
9#include"stdlib.h"
10#include"alloc.h"
11
12/*树中结点存储结构*/
13typedefstructBiTNode{
14chardata;/*存储数据*/
15structBiTNode*lchild,*rchild;/*左右孩子*/
16}BiTNode,*BiTree;
17
18
19/*销毁二叉树*/
20voidDestoryBiTree(BiTreet){
21if(!
t->lchild&&!
t->rchild){
22free(t);
23}else{
24while(t->lchild){
25DestoryBiTree(t->lchild);
26}
27while(t->rchild){
28DestoryBiTree(t->lchild);
29}
30
31}
32}
33
34
35/*清空二叉树*/
36voidClearBiTree(BiTreet){
37t->data='';
38if(t->lchild){
39ClearBiTree(t->lchild);
40}
41if(t->rchild){
42ClearBiTree(t->rchild);
43}
44}
45
46/*判空二叉树*/
47intBiTreeEmpty(BiTreet){
48if(t==NULL){
49return1;
50}
51else
52return0;
53}
54
55
56/*求二叉树深度*/
57intBiTreeDepth(BiTreet){
58
59intsuml=0;/*左子树深度*/
60intsumr=0;/*右子树深度*/
61
62if(suml>=sumr){
63returnsuml+1;
64}else
65returnsumr+1;
66}
67
68/*返回二叉树的根*/
69charRoot(BiTreet){
70returnt->data;
71}
72/*插入结点,p为双亲结点指针,lr为左右孩子标记,c为值*/
73voidInsertChild(BiTreet,BiTreep,intlr,charc){
74if(t==p){
75if(lr==0){
76p->lchild=(BiTree)malloc(sizeof(BiTNode));
77p->lchild->lchild=NULL;
78p->lchild->rchild=NULL;
79p->lchild->data=c;
80}else{
81
82p->rchild=(BiTree)malloc(sizeof(BiTNode));
83p->rchild->rchild=NULL;
84p->rchild->rchild=NULL;
85p->rchild->data=c;
86}
87}else{
88if(t->lchild)
89InsertChild(t->lchild,p,lr,c);
90if(t->rchild)
91InsertChild(t->rchild,p,lr,c);
92}
93}
94/*删除结点,p为双亲结点,lr为左右孩子标记*/
95voidDeleteChild(BiTreet,BiTreep,intlr){
96
97if(t==p){
98if(lr==0){
99free(p->lchild);
100}else{
101
102free(p->rchild);
103}
104}else{
105if(t->lchild)
106DeleteChild(t->lchild,p,lr);
107if(t->rchild)
108DeleteChild(t->rchild,p,lr);
109}
110}
遍历操作:
[cpp]viewplaincopyprint?
111/*6.1遍历二叉树,先序,中序,后序(递归实现)
112**Author:
Kevin
113**Date:
2011/11/30
114*/
115
116
117#include"stdio.h"
118#include"alloc.h"
119#include"stdlib.h"
120
121#defineELEMint
122#defineStatusint
123
124
125typedefstructMyTree{
126ELEMmyNode;/*节点定义*/
127structmyTree*leftChild;/*左子树*/
128structmyTree*rightChild;/*右子树*/
129}MyTree,*MyLTree;
130
131/*按照定义递归构造二叉数*/
132voidCreateTree(MyLTreemt,intlevel){
133
134intdu;
135inti;
136intj;
137intleftOrRight;
138MyLTreep=NULL;
139MyLTreeq=NULL;
140q=mt;
141if(!
mt->leftChild||!
mt->rightChild){
142mt->leftChild=NULL;
143mt->rightChild=NULL;
144}
145printf("&&Pleaseinputthis%dnodesdu;\n",level);
146scanf("%d",&du);
147if(du>2||du<0){
148printf("Erroroccur,duiserror!
\n");
149return0;
150}
151elseif(du==1){
152printf("Pleasegooninputtheleftorright,1left,2right!
\n");
153scanf("%d",&leftOrRight);
154if(leftOrRight==1){
155for(j=0;j 156p=(MyLTree)malloc(sizeof(MyTree)); 157p->leftChild=NULL; 158p->rightChild=NULL; 159printf("pleaseinput%dleftchildvalue\n",level); 160scanf("%d",&p->myNode); 161q->leftChild=p; 162CreateTree(p,p->myNode); 163} 164} 165else{ 166for(j=0;j 167p=(MyLTree)malloc(sizeof(MyTree)); 168p->leftChild=NULL; 169p->rightChild=NULL; 170printf("pleaseinput%drightchildvalue\n",level); 171scanf("%d",&p->myNode); 172q->rightChild=p; 173CreateTree(p,p->myNode); 174} 175} 176 177} 178elseif(du==2){ 179for(j=0;j 180if(j==0){ 181p=(MyLTree)malloc(sizeof(MyTree)); 182p->leftChild=NULL; 183p->rightChild=NULL; 184printf("pleaseinputthe%dleftchildvalue\n",level); 185scanf("%d",&p->myNode); 186q->leftChild=p; 187CreateTree(p,p->myNode); 188}else{ 189p=(MyLTree)malloc(sizeof(MyTree)); 190p->leftChild=NULL; 191p->rightChild=NULL; 192printf("pleaseinputthe%drightchildvalue\n",level); 193scanf("%d",&p->myNode); 194q->rightChild=p; 195CreateTree(p,p->myNode); 196} 197 198} 199} 200else{ 201printf("thisistheleafnode\n"); 202} 203 204} 205 206/*先序*/ 207voidpreOrderTree(MyLTreemt){ 208printf("%d\n",mt->myNode); 209if(mt->leftChild){ 210preOrderTree(mt->leftChild); 211} 212if(mt->rightChild){ 213preOrderTree(mt->rightChild); 214} 215} 216 217/*中序*/ 218voidinOrderTree(MyLTreemt){ 219if(mt->leftChild){ 220inOrderTree(mt->leftChild); 221} 222printf("%d\n",mt->myNode); 223if(mt->rightChild){ 224inOrderTree(mt->rightChild); 225} 226} 227 228/*后序*/ 229voidposOrderTree(MyLTreemt){ 230if(mt->leftChild){ 231posOrderTree(mt->leftChild); 232} 233if(mt->rightChild){ 234posOrderTree(mt->rightChild); 235} 236printf("%d\n",mt->myNode); 237} 238 239 240 241intmain(){ 242MyLTreepm; 243intt=1; 244pm=(MyLTree)malloc(sizeof(MyTree)); 245pm->leftChild=NULL; 246pm->rightChild=NULL; 247 248printf("*************Pleaseinputtherootnodevalue: ****************\n"); 249scanf("%d",&pm->myNode); 250 251CreateTree(pm,t); 252printf("\n"); 253/*先序遍历*/ 254printf("Thepreasbelow: \n"); 255preOrderTree(pm); 256printf("\n"); 257printf("Theinasbelow: \n"); 258/*中顺遍历*/ 259inOrderTree(pm); 260printf("\n"); 261printf("Theposasbelow: \n"); 262/*后顺遍历*/ 263posOrderTree(pm); 264printf("\n"); 265 266printf("Pleaseinputanykeytocontinue(^_^)\n"); 267getchar(); 268getchar(); 269 270 271 272} 273 按照定义创建二叉树 [cpp]viewplaincopyprint? 274StatusCreateBiTree(BiTree&T){ 275scanf(&ch); 276if(ch=='') 277T=NULL; 278else{ 279if(! (T=(BiTNode*)malloc(sizeof(BiTNode))))exit(OVERFLOW); 280T->data=ch; 281CreateBiTree(T->lchild); 282CreateBiTree(T->rchild); 283} 284} 输入ABC___D_E__(下划线代表空格) 利用二叉树存储表达式(表达市求值) 一般情况: 左子树(存储第一操作数),右子树(存储第二操作数),根(存储运算符).如果第一操作数或者第二操作数还是个表达式,则递归之. 例如: (a+b)*c-d/e,按照先缀表示法为: -*+abc/de,那么如果根据先缀生成一棵二叉树(按照先序遍历),由于此操作树比为满二叉树,另外形式为根是运算符,两个儿子分别是第一操作数和第二操作树,同样后序也可以生成一个二叉树,只不过需要后序生成.操作数必为一个叶子结点.运算符的左右子树都不空, 前缀和后缀表达式,都可以建树. 原表达式建树: 原表达式->后缀->树(一起形成) 建立两个栈(分别存运算符和操作数),当形成一个小的子树时,保存子树的根指针,依此类推. 线索二叉树 遍历二叉树的结果是求得结点的一个线性序列,指向该线性序列的"前驱"和"后继"的指针,称为"线索". 作用: 当以二叉树作为存储结构时,只能找到结点的左右孩子,不能找到它在线性序列中的前驱和后继,所以就形成了线索二叉树. 线索二叉树存储结构: 左子树为空,加前驱.右子树为空,加后继.(这里要注意,线索二叉树的前驱与后继是要根据遍历的顺序决定的) typedefenumPointerTag{Link,Thread}PointerTag;//link==0指针,Trhread==1线索 typedefstructBiThrNode{ ElemTypedata; structBiThrNode*lchild,*rcihi
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构
![提示](https://static.bdocx.com/images/bang_tan.gif)