已知一棵二叉树是以二叉链表的形式存储的求出以T为根的子树的结点个数和高度

作者&投稿:向东 (若有异议请与网页底部的电邮联系)
已知一棵二叉树是以二叉链表的形式存储的,其结点结构说明如下: struct node { int data; struct node *~

#include
#include

/*①、求出以T为根的子树的结点个数。
②、求出以T为根的子树的高度。*/

typedef struct node
{
int data;
struct node * left;
struct node * right;
}BiTNode,*BiTree;

/*①、求出以T为根的子树的结点个数。*/
void CountLeaf (BiTree T, int& count)
{ //递归方法,
if ( T )
{
if ((!T->lchild)&& (!T->rchild))
count++;
CountLeaf( T->lchild, count); // 统计左子树中叶子结点个数
CountLeaf( T->rchild, count); // 统计右子树中叶子结点个数
}
}

/*②、求出以T为根的子树的高度。*/
int Depth(BinTree *T)
{
int dep1,dep2;
if(T==Null) return(0);
else
{
dep1=Depth(T->lchild);
dep2=Depth(T->rchild);
return dep1 > dep2 ? dep1 +1 : dep2 + 1;
}

先前序遍历整个二叉树,找到符合要求的结点,然后后序遍历该结点的整个子树,逐一释放结点。
//假设二叉树结构体如下struct binTree{ int data; binTree *lchild; binTree *rchild;}*BiTree;//函数如下BiTree find(BiTree node, int x){ if(node) { if(node->data==x) delete(node); else { find(node->lchild); find(node->rchild); } }}BiTree delete(BiTree tree){ if(node) { delete(node->lchild); delete(node->rchild); free(node); node=NULL; }}

5.1树的概念

树的递归定义如下:(1)至少有一个结点(称为根)(2)其它是互不相交的子树

1.树的度——也即是宽度,简单地说,就是结点的分支数。以组成该树各结点中最大的度作为该树的度,如上图的树,其度为3;树中度为零的结点称为叶结点或终端结点。树中度不为零的结点称为分枝结点或非终端结点。除根结点外的分枝结点统称为内部结点。
2.树的深度——组成该树各结点的最大层次,如上图,其深度为4;
3.森林——指若干棵互不相交的树的集合,如上图,去掉根结点A,其原来的二棵子树T1、T2、T3的集合就为森林;
4.有序树——指树中同层结点从左到右有次序排列,它们之间的次序不能互换,这样的树称为有序树,否则称为无序树。
5.树的表示
树的表示方法有许多,常用的方法是用括号:先将根结点放入一对圆括号中,然后把它的子树由左至右的顺序放入括号中,而对子树也采用同样的方法处理;同层子树与它的根结点用圆括号括起来,同层子树之间用逗号隔开,最后用闭括号括起来。如上图可写成如下形式:
(A(B(E(K,L),F),C(G),D(H(M),I,J)))
5. 2 二叉树
1.二叉树的基本形态:
二叉树也是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:

(1)空二叉树——(a);
(2)只有一个根结点的二叉树——(b);
(3)右子树为空的二叉树——(c);
(4)左子树为空的二叉树——(d);
(5)完全二叉树——(e)
注意:尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。

2.两个重要的概念:
(1)完全二叉树——只有最下面的两层结点度小于2,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树;
(2)满二叉树——除了叶结点外每一个结点都有左右子女且叶结点都处在最底层的二叉树,。
如下图:

完全二叉树

满二叉树

3.二叉树的性质
(1) 在二叉树中,第i层的结点总数不超过2^(i-1);

(2) 深度为h的二叉树最多有2h-1个结点(h>=1),最少有h个结点;
(3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,

则N0=N2+1;

(4) 具有n个结点的完全二叉树的深度为int(log2n)+1
(5)有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:

若I为结点编号则 如果I<>1,则其父结点的编号为I/2;
如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;
如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。
4.二叉树的存储结构:
(1)顺序存储方式

type node=record

data:datatype

l,r:integer;

end;

var tr:array[1..n] of node;

(2)链表存储方式,如:
type btree=^node;

node=record

data:datatye;

lchild,rchild:btree;

end;

5.普通树转换成二叉树:凡是兄弟就用线连起来,然后去掉父亲到儿子的连线,只留下父母到其第一个子女的连线。

6.二叉树的遍历运算(递归定义)
(1)先序遍历
访问根;按先序遍历左子树;按先序遍历右子树
(2)中序遍历
按中序遍历左子树;访问根;按中序遍历右子树
(3)后序遍历
按后序遍历左子树;按后序遍历右子树;访问根

例1.用顺序存储方式建立一棵有31个结点的满二叉树,并对其进行先序遍历。
program erchashu1;
var b:array[1..31] of char;
e:array[1..63] of byte;
n,h,i,k:integer;
procedure tree(t:integer);
begin
if e[t]=0 then exit
else
begin
write(b[t]);e[t]:=0;
t:=2*t;tree(t);
t:=t+1;tree(t);
end;
end;
begin
repeat
write('n=');readln(n);
until (n>0) and (n<6);
fillchar(e,sizeof(e),0);
k:=trunc(exp(n*ln(2)))-1;
for i:=1 to k do e[i]:=1;
for i:=1 to 26 do b[i]:=chr(64+i);
for i:=1 to 5 do b[26+i]:=chr(48+i);
h:=1 ;tree(h);
writeln;
end.

例2.用顺序存储方式建立一棵如图所示的二叉树,并对其进行先序遍历。

program tree1;
const n=15;
type node=record
data:char;
l,r:0..n;
end;
var tr:array[1..n] of node;
e:array[1..n] of 0..1;
i,j:integer;

procedure jtr;
var i:integer;
begin
for i:=1 to n do
with tr[i] do
readln(data,l,r);
end;
procedure search(m:integer);
begin
with tr[m] do
begin
write(data);
if l<>0 then search(l);
if r<>0 then search(r);
end;
end;
begin
jtr;search(1);writeln;
end.

例3 用链表存储方式生成上述二叉树,中序遍历之。

1.将上述二叉树用广义表表示为A(B(D,E(G)),C(F(,H)))

2.根据广义表串(以#结束)生成二叉树。

program ltree;
const n=8;
type trlist=^node;
node=record
da:char;
l,r:trlist;
end;
var s:array[1..n] of trlist;
p,root:trlist;
ch:char;
top,k:integer;
procedure creat(var head:trlist);
begin
read(ch);
top:=0;
while ch<>'#' do
begin
case ch of
'A'..'Z':begin new(p);p^.da:=ch;p^.l:=nil;p^.r:=nil;
if top<>0 then
case k of
1:s[top]^.l:=p;
2:s[top]^.r:=p;
end
end;
'(':begin top:=top+1;s[top]:=p;k:=1;end;
')': top:=top-1;
',': k:=2;
end;
read(ch);
end;
head:=s[1];
end;
procedure inorder(head:trlist);
begin
if head^.l<>nil then inorder(head^.l);
write(head^.da);
if head^.r<>nil then inorder(head^.r);
end;
begin
write('Input tree string:');
creat(root);
inorder(root);
end.

5.3 二叉树的应用
1. 哈夫曼树与哈夫曼码

树的路径长度:一棵树的每一个叶结点到根结点的路径长度的和。

带权二叉树:给树的叶结点赋上某个实数值(称叶结点的权)。

带权路径长度:各叶结点的路径长度与其权值的积的总和。

哈夫曼树(最优二叉树):带权路径长度最小的二叉树。

如何构建哈夫树:(思想是:权越大离跟越近)

program gojiantree;
const n=4;m=7;
type node=record
w:real;
parent,lchild,rchild:0..m
end;
htree=array[1..m] of node;
var htree1:htree;
procedure gjtree(var ht:htree);
var i,j:integer;
small1,small2:real;
p1,p2:0..m;
begin
for i:=1 to m do
with ht[i] do
begin
w:=0;lchild:=0;rchild:=0;parent:=0;
end;
for i:=1 to n do read(ht[i].w);
for i:=n+1 to m do
begin
p1:=0;p2:=0;
small1:=1000;small2:=1000;
for j:=1 to i-1 do
if ht[j].parent=0 then
if ht[j].w<small1 then
begin small2:=small1;small1:=ht[j].w;p2:=p1;p1:=j end
else if ht[j].w<small2 then begin small2:=ht[j].w;p2:=j end;
ht[p1].parent:=i;
ht[p2].parent:=i;
ht[i].lchild:=p1;
ht[i].rchild:=p2;
ht[i].w:=ht[p1].w+ht[p2].w;
end;
end;
begin
gjtree(htree1);
end.

哈夫曼码:哈夫曼树的非叶结点到左右孩子的路径分别用0,1 表示,从根到叶的路径序列即为哈夫曼码。

哈夫曼码是不会发生译码多义性的不等长编码,广泛应用实际中。

(原因是任何一字符的编码不是更长编码的前缀部分,为什么?)

2.排序二叉树

排序二叉树:每一个参加排列的数据对应二叉树的一个结点,且任一结点如果有左(右)子树,则左(右)子树各结点的数据必须小(大)于该结点的数据。中序遍历排序二叉树即得排序结果。程序如下:

program pxtree;
const
a:array[1..8] of integer=(10,18,3,8,12,2,7,3);
type point=^nod;
nod=record
w:integer;
right,left:point ;
end;
var root,first:point;k:boolean;i:integer;
procedure hyt(d:integer;var p:point);
begin
if p=nil then
begin
new(p);
with p^ do begin w:=d;right:=nil;left:=nil end;
if k then begin root:=p; k:=false end;
end
else with p^ do if d>=w then hyt(d,right) else hyt(d,left);
end;
procedure hyt1(p:point);
begin
with p^ do
begin
if left<>nil then hyt1(left);
write(w:4);
if right<>nil then hyt1(right);
end
end;
begin
first:=nil;k:=true;
for i:=1 to 8 do hyt(a[i],first);
hyt1(root);writeln;
end.

3.堆排序

堆:设有数据元素的集合(R1,R2,R3,...Rn)它们是一棵顺序二叉树的结点且有

Ri<=R2i 和Ri<=R2i+1(或>=)

堆的性质:堆的根结点上的元素是堆中的最小元素,且堆的每一条路径上的元素都是有序的。

堆排序的思想是:

1)建初始堆(将结点[n/2],[ n/2]-1,...3,2,1分别调成堆)

2)当未排序完时

输出堆顶元素,删除堆顶元素,将剩余的元素重新建堆。

程序如下:

program duipx;
const n=8;
type arr=array[1..n] of integer;
var a:arr;i:integer;
procedure sift(var a:arr;l,m:integer);
var i,j, t:integer;
begin
i:=l;j:=2*i;t:=a[i];
while j<=m do
begin
if (j<m) and (a[j]>a[j+1]) then j:=j+1;
if t>a[j] then
begin a[i]:=a[j];i:=j;j:=2*i; end
else exit;
end;
a[i]:=t;
end;
begin
for i:=1 to n do read(a[i]);
for i:=(n div 2) downto 1 do
sift(a,i,n);
for i:=n downto 2 do
begin
write(a[1]:4);
a[1]:=a[i];
sift(a,1,i-1);
end;
writeln(a[1]:4);
end

int depth(T)
{
if(!T)
depthval=0;
else
{
depthLeft=depth(T->lchild);
depthRight=depth(T->rchild);
depthval=(depthLeft>depthRight?depthLeft:depthRight);
}
return depthval;
}


已知一棵完全二叉树树中有234个结点,问树的高度数多少
h+1) - 1 完全二叉树的节点个数为:2^h ~ 2^(h+1) - 1 原因很简单,完全二叉树在h层可以是只有一个节点(2^(h-1+1) - 1+1 = 2^h),一直到构成满二叉树(2^(h+1) - 1)所以,经过上面的分析之后,这个题目就很好算了:2^8 = 256 2^9 = 512 所以树的高度就是8 ...

已知一棵满二叉树有47个结点,则该二叉树有多少个叶子结点!?
满二叉树是一种特殊的二叉树,它的每一层都是完全填满的,且所有的叶子节点都在同一层。因此,满二叉树的叶子节点数就是其节点总数的一半。所以,该满二叉树的叶子节点数为 47 \/ 2 = 23.5。然而,在计算机科学中,通常会取整计算。因此,我们可以说该满二叉树的叶子节点数为 23(向下取整)。

已知一棵二叉树的前序序列为A B D G C E H I F;中序序列为:D G B A...
二叉树的后序为G、D、B、I、H、E、F、C、A。由前前序第一个为A,所以根节点,所以A的左子树为D、G、B,右子树为E、I、H、C、F。第二个根节点为B,又由中序的出B的左子树为D、G,然后得出D的右子树为G,C为A的右子树,依次进行判断,最后的出二叉树的序列。二叉树图,如下图:...

已知一棵二叉树前序遍历和中序遍历分别为ABDEGCFH和DBGEACHF,则该二叉...
已知一棵二叉树前序遍和中序遍历分别为ABDEGCFH和DBGEACHF,则该二叉树的后序遍历是DGEBHFCA。前序遍历的第一个节点为根节点,由前序遍历可知,A为根节点。中序遍历的根节点前面的节点均为左子树的节点,所以左子树上的节点为DBGE。去掉根节点和左子树节点,右子数节点为CHF。前序遍历的第二个节点...

一棵度为2的树与一棵二叉树有何区别?
2、分支不同 度为2的树有两个分支,但分支没有左右之分;一棵二叉树也有两个分支,但有左右之分,左右子树的次序不能随意颠倒。3、次序不同 度为2的树从形式上看与二叉树很相似,但它的子树是无序的,而二叉树是有序的。即,在一般树中若某结点只有一个孩子,就无需区分其左右次序,而在二叉...

什么是二叉树?二叉树拿来干什么?
二叉树常被用作二叉查找树和二叉堆。二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2的(i-1)次方个结点;深度为k的二叉树至多有2^(k) -1个结点;对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为n0,度为2的...

某二叉树中度为2的结点有18个,则该二叉树中有【 】个叶子结点
没有子树的结点或者度为零的结点;根据二叉树的一个性质:若在任意一棵二叉树中,有n个叶子节点,有n₂个度为2的节点,则必有n₀=n₂+1,可以得到,叶子节点的数目等于度为2的节点的数目加1;所以,某二叉树中度为2的结点有18个,则该二叉树中有18+1=19个叶子结点。

二叉树的度是什么含义?1度,2度是什么意思?
并且每一个顶点的度不大于3。在二叉树中,一棵深度为k,且有2^k-1个节点的二叉树,称为满二叉树。这种树的特点是每一层上的节点数都是最大节点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则此二叉树为完全二叉树。

若一棵二叉树的任一非叶子结点的度为2,则该二叉树是( )
如下形态的二叉树 o \/ \\ 0 0 \/ \\ 0 0这个就不是完全二叉树也不是满二叉树,这只是哈夫曼树。

求二叉树的总结点数
二叉树一个结点下面可能有两个子结点(度为2),也可能有一个子结点(度为1),或者没有子结点(度为0,也叫叶子结点)那么在这棵树中只可能出现三种情况:度为2,度为1,度为0(叶子结点)。不可能出现其他情况,否则就不是二叉树了。所以,总结点数应该为三者之和。已经知道:度为0=70,度为...

吉木乃县14757697332: 已知一棵二叉树是以二叉链表的形式存储的,其结点结构说明如下: struct node { int data; struct node * 已知一棵二叉树是以二叉链表的形式存储的,其结点... -
言胁安立:[答案] #include#include/*①、求出以T为根的子树的结点个数.②、求出以T为根的子树的高度.*/typedef struct node{ int data; struct node * left; struct node * right;}BiTNode,*BiTree;/*①、求出以T为根的子树的结点...

吉木乃县14757697332: 已知一棵二叉树采用二叉链表存放,写依程序,要求统计出二叉树中叶子的个数,并输出二叉树中非终端节点 -
言胁安立: void countleaf(bitnode *t,int *c) { if(t!=null) { if (t->lchild==null && t->rchild==null) {*c=*c+1; } countleaf(t->lchild,c); countleaf(t->rchild,c); } return; } typedef struct bitnode { char data; struct bitnode *lchild, *rchild; }bitnode, *bitree;

吉木乃县14757697332: 已知一个二叉树存储于二叉链表中, -
言胁安立: 定义单向链表,储存内容为二叉树节点的指针.判断当前二叉树节点是否还有子树,有的话就将子树节点一并存入链表,然后链表指针指向下一节点,检查其中的二叉树节点.如此循环,直到所有二叉树节点都存入链表为止.此时链表的长度就是节点总数.求深度需要两个这样的链表,进行广度优先的便利,每完成一层深度加一,全部叶节点遍历完就能得出深度.

吉木乃县14757697332: 设一棵二叉树以二叉链表为存储结构,试写出求该二叉树中所有叶子结点数的算法. -
言胁安立: //我做了一个程序,可以实现二叉树的左右子树的交换功能,#include<iostream.h>/* 二叉树类型的定义(二叉链表形式储存) */ typedef char datatype; // 树的结点数据类型为字符型,可以根据需要修改 typedef struct node *pointer; // 定义二叉...

吉木乃县14757697332: 设一棵二叉树以二叉链表为存储结构 -
言胁安立: void Leaf(BiTree T) {if(T=null){ return 0; } elseif(T->lchild==null&&T->rchild==null){ return 1; } else return leaves(T->lchild)+leaves(T->rchild); }

吉木乃县14757697332: 已知一棵二叉树以二叉链表为存储结构,编写如下程序:对于树中每一个元素值为x的结点,删去以它为根的子 -
言胁安立: 先前序遍历整个二叉树,找到符合要求的结点,然后后序遍历该结点的整个子树,逐一释放结点.//假设二叉树结构体如下 struct binTree { int data; binTree *lchild; binTree *rchild; }*BiTree;//函数如下 BiTree find(BiTree node, int x) { if(node) { if(...

吉木乃县14757697332: 已知一棵完全二叉树采用链表存放,写一算法,要求统计出二叉树中非终端节点的个数 -
言胁安立: 1、计算出树的深度d.2、因为是完全二叉树,所以非终端节点个数={2^(d-1)}-1//递归求树的深度 int depth(TreeNode *T) { if(T==NULL)return 0; else { return max(depth(T->left),depth(T->right))+1;} }//计算完全二叉树,非叶节点的个数 int countNode(TreeNode *T) { int d=depth(T); return pow(2,d-1)-1; }

吉木乃县14757697332: 已知二叉树以二叉链表做为存储结构,阅读算法并回答下列问题:(1)该算法的功能是什么(2)算法中的n的作 -
言胁安立: 该算法的功能是前序遍历二叉树,统计二叉树中含有左右两个孩子的结点的个数.n的作用是统计二叉树中含有左右两个孩子的结点的个数.

吉木乃县14757697332: 数据结构算法设计题1.已知一颗二叉树采用二叉链表存放,写一算法,要求统计出二叉树中叶子结点个数并输出(输出无顺序要求)1.已知一个带头结点的... -
言胁安立:[答案] 某链表中最常用的操作是在最后一个元素之后插入一个元素和删除最后一个元素,则采用( )存储方式最节省运算时间.(A)...已知带头结点的单链表L中的结点是按整数值递增排列的,试写一算法,将值为x 的结点插入到表L中,使得L仍然有序

吉木乃县14757697332: 编写算法:已知二叉排序树按二叉链表形式存储,树中结点各不相同,欲得到一个由小到大的结点值递增序列 -
言胁安立: 首先看下二叉排序树的定义:二叉排序树(Binary Sort Tree)又称二叉查找树,亦称二叉搜索树. 它或者是一棵空树;或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网