数据结构自学总结2非线性结构Word文档下载推荐.docx
《数据结构自学总结2非线性结构Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《数据结构自学总结2非线性结构Word文档下载推荐.docx(42页珍藏版)》请在冰豆网上搜索。
任意一个节点的子节点的个数都不受限制的树
2二叉树:
任意一个节点的子节点个数最多两个,且子节点的位置不能更改。
二叉树的分类:
一般二叉树,
满二叉树:
在不增加树的层次的前提下,无法再多添加一个节点的二叉树就是满二叉树。
完全二叉树:
如果只是删除了满二叉树最底层最右边的连续若干个节点,这样形成的二叉树就是完全二叉树。
3森林:
n个互不相交的树的集合。
树的存储:
二叉树的存储:
连续存储(完全二叉树)
优点:
查找某个节点的父节点和子节点(也包括判断有没有节点)很方便
缺点:
耗用的内存很大。
链式存储:
一般树的存储:
1双亲存储表示法:
求父节点方便
2孩子链式表示法:
求子节点方便
3双亲孩子表示法:
求父节点和子节点都很方便
4孩子兄弟链式表示法:
把一个普通树转化成二叉树来存储
具体的转换方法:
设法保证任意一个节点的左指针域指向他的第一个孩子,右指针域指向他的堂兄弟,只要能满足此条件,就可以把一个普通树转化为一个二叉树。
一个普通树转化成德二叉树一定没有右子树。
森林的存储:
先把森林转化为二叉树,再存储二叉树
树的操作:
1遍历
先序遍历(根左右)
中序遍历(左根右)
后序遍历(左右根)
2已知两种遍历序列求原始二叉树:
1已知先序遍历和中序遍历:
根据先序遍历确定根节点,再根据先序遍历确定根节点左子树和右子树的根(最先出现的即为所选),根据中序遍历和先序遍历一次确定该二叉树。
2已知中序遍历和后序遍历:
根据后序遍历确定根节点,再根据中序遍历确定左子树和右子树有哪些,在判断左右子树的根节点(左右子树的序列中根据中序遍历,最后出现的即为根节点。
)
(注:
已知先序遍历和后序遍历是无法还原出原始的二叉树的)也就是说只有通过先序和中序或者通过中序和后序我们才能唯一的确定一个二叉树。
树的应用:
树是数据库中数据组织的一种重要形式
操作系统子父进程的关系本身就是一棵树
面向对象语言中类的继承关系本身就是一颗二叉树
哈弗曼树(最优二叉树)
1二叉树的各种方法的实现
/*
2012年3月19日16:
51:
01作者:
陈金林
目的:
实现二叉树的各种算法
*/
#include<
stdio.h>
stdlib.h>
#defineMaxSize50
typedefcharElemType;
typedefstructnode
{
ElemTypedata;
//数据元素
structnode*lchild;
//指向左孩子
structnode*rchild;
//指向右孩子
}BTNode;
externvoidCreateBTNode(BTNode*&
b,char*str);
externBTNode*FindNode(BTNode*b,ElemTypex);
externBTNode*LchildNode(BTNode*p);
externBTNode*RchildNode(BTNode*p);
externintBTNodeDepth(BTNode*b);
externvoidDispBTNode(BTNode*b);
externintBTWidth(BTNode*b);
externintNodes(BTNode*b);
externintLeafNodes(BTNode*b);
intmain(void)
BTNode*b,*p,*lp,*rp;
;
CreateBTNode(b,"
A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))"
);
printf("
\n"
\n===========二叉树的各个方法的实现=============\n"
(1)输出二叉树:
"
DispBTNode(b);
(2)'
H'
结点:
p=FindNode(b,'
if(p!
=NULL)
{
lp=LchildNode(p);
if(lp!
=NULL)
printf("
左孩子为%c"
lp->
data);
else
无左孩子"
rp=RchildNode(p);
if(rp!
右孩子为%c"
rp->
无右孩子"
}
(3)二叉树b的深度:
%d\n"
BTNodeDepth(b));
(4)二叉树b的宽度:
BTWidth(b));
(5)二叉树b的结点个数:
Nodes(b));
(6)二叉树b的叶子结点个数:
LeafNodes(b));
return0;
}
voidCreateBTNode(BTNode*&
b,char*str)//由str串创建二叉链
BTNode*St[MaxSize],*p=NULL;
inttop=-1,k,j=0;
charch;
b=NULL;
//建立的二叉树初始时为空
ch=str[j];
while(ch!
='
\0'
)//str未扫描完时循环
switch(ch)
{
case'
('
:
top++;
St[top]=p;
k=1;
break;
//为左结点
)'
top--;
break;
'
k=2;
//为右结点
default:
p=(BTNode*)malloc(sizeof(BTNode));
p->
data=ch;
p->
lchild=p->
rchild=NULL;
if(b==NULL)//p指向二叉树的根结点
b=p;
else//已建立二叉树根结点
{
switch(k)
{
case1:
St[top]->
lchild=p;
case2:
rchild=p;
}
}
}
j++;
ch=str[j];
BTNode*FindNode(BTNode*b,ElemTypex)//返回data域为x的结点指针
BTNode*p;
if(b==NULL)
returnNULL;
elseif(b->
data==x)
returnb;
else
{
p=FindNode(b->
lchild,x);
if(p!
returnp;
else
returnFindNode(b->
rchild,x);
BTNode*LchildNode(BTNode*p)//返回*p结点的左孩子结点指针
returnp->
lchild;
BTNode*RchildNode(BTNode*p)//返回*p结点的右孩子结点指针
rchild;
intBTNodeDepth(BTNode*b)//求二叉树b的深度
intlchilddep,rchilddep;
if(b==NULL)
return(0);
//空树的高度为0
lchilddep=BTNodeDepth(b->
lchild);
//求左子树的高度为lchilddep
rchilddep=BTNodeDepth(b->
rchild);
//求右子树的高度为rchilddep
return(lchilddep>
rchilddep)?
(lchilddep+1):
(rchilddep+1);
voidDispBTNode(BTNode*b)//以括号表示法输出二叉树(此处用的是先序遍历)
if(b!
printf("
%c"
b->
if(b->
lchild!
=NULL||b->
rchild!
("
DispBTNode(b->
if(b->
=NULL)printf("
"
)"
/*
voidDispBTNode1(BTNode*b)//以括号表示法输出二叉树(此处用的是中序遍历)
voidDispBTNode2(BTNode*b)//以括号表示法输出二叉树(此处用的是后序遍历)
intBTWidth(BTNode*b)//求二叉树b的宽度
struct
intlno;
//结点的层次编号
BTNode*p;
//结点指针
}Qu[MaxSize];
//定义顺序非循环队列
intfront,rear;
//定义队首和队尾指针
intl