树形结构.docx

上传人:b****8 文档编号:9330706 上传时间:2023-02-04 格式:DOCX 页数:17 大小:67.41KB
下载 相关 举报
树形结构.docx_第1页
第1页 / 共17页
树形结构.docx_第2页
第2页 / 共17页
树形结构.docx_第3页
第3页 / 共17页
树形结构.docx_第4页
第4页 / 共17页
树形结构.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

树形结构.docx

《树形结构.docx》由会员分享,可在线阅读,更多相关《树形结构.docx(17页珍藏版)》请在冰豆网上搜索。

树形结构.docx

树形结构

树形结构——二叉树

相关知识:

一维数组|多维数组|栈|队列|串

一、树的基本术语

       

  1.树的度——也即是宽度,以组成该树各结点中最大的度作为该树的度,如上图的树,其度为3;

  2.树的深度——以组成该树各结点的最大层次,如上图,其深度为4;

  3.森林——指若干棵互不相交的树的集合,如上图,去掉根结点A,其原来的二棵子树T1、T2、T3的集合{T1,T2,T3}就为森林;

  4.有序树——指树中同层结点从左到右有次序排列,它们之间的次序不能互换,这样的树称为有序树,否则称为无序树。

二、树的表示

  树的表示方法有许多,常用的方法是用括号:

先将根结点放入一对圆括号中,然后把它的子树由左至右的顺序放入括号中,而对子树也采用同样的方法处理;同层子树与它的根结点用圆括号括起来,同层子树之间用逗号隔开,最后用闭括号括起来。

如上图可写成如下形式:

    (A(B(E(K,L),F),C(G),D(H(M),I,J)))

三、二叉树

1.二叉树的基本形态:

  二叉树也是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:

     

  

(1)空二叉树——(a);

  

(2)只有一个根结点的二叉树——(b);

  (3)右子树为空的二叉树——(c);

  (4)左子树为空的二叉树——(d);

  (5)完全二叉树——(e)

2.两个重要的概念:

  

(1)完全二叉树——只有最下面的两层结点度小于2,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树;

  

(2)满二叉树——除了叶结点外,每一个结点都有左右子女的二叉树。

  如下图:

            

   

满二叉树

完全二叉树

3.二叉树的性质

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

(2)对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点(有左右子节点)总数为N2,则N0=N2+1;

如上图(左):

N0=6,N2=5右图:

N0=8,N2=7(3)有N个结点的完全二叉树各结点如果用顺序方式表示,则结点之间有如下关系:

·如果I<>1,则其父结点的编号为[I/2];

·如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;

·如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。

(4)具有n个节点的完全二叉树的深度为[log2N]+1

4.二叉树的存储结构:

(1)顺序存储方式

        

图5

问题:

对于用顺序结构来表示的二叉树

A.如何根据节点顺序编号确定所层数和从左数起的编号;

反之如何根据层数和从左数起的编号确定节点顺序编号

B.如何根据节点顺序编号确定其父节点编号。

C.如何根据节点顺序编号确定其左右子节点编号

(2)链表存储方式,

A.采用数组类型

constmax=……{二叉树的存储容量}

TYPE

Datetype=……{节点信息类型}

Nodetype=recod

Data:

datatype;{信息域}

Lchild,rchild:

integer;{左右指针}

End;

VARlist:

array[1..max]ofnodetype;

应用形式:

list[I].data=……

list[list[I].lchild]:

=....{左节点}

list[list[I].rchild]:

=....{右节点}

如:

图5

数组下标:

    1 2 3 4 5 6 7 8

 数组D:

     A B C D E F G H

 左指针数组L:

  2 4 6 0 7 0 0 0

右指针数组R:

  3 5 0 0 0 8 0 0

B.采用动态数据类型

type

datatype=....

link=^nodetype

nodetype=recod

data:

datatype;{信息域}

lchild,rchild:

link;{左右指针}

end;

VARt:

link;

应用形式:

t^.data:

=....;t^.lchild:

=..;{左子节点}t^.rchild:

=..;{右子节点}

5.二叉树的遍历运算(递归定义)

A

BC

DEF

GHI

图6

(1)先序遍历ABDEGCFHI

递归定义

访问根;

按先序遍历左子树;

按先序遍历右子树。

算法如下

动态类型数组类型

typeconstmax=……

datatype=....Datetype=……

link=^nodetypeNodetype=recod

nodetype=recodData:

datatype;

data:

datatype;L,r:

integer;

l,r:

link;end;

end;VARlist:

array[1..max]ofnodetype;

VARt:

link;

proceduremake(t:

link);proceduremake(t:

intger);

beginbegin

ift<>nilthenift<>0then

beginbegin

访问t^.data访问list[t].data

make(t^.l);make(list[t].l);

make(t^.r);make(list[t].r);

end;end;

end;end;

(2)中序遍历DBGEACHFI

递归定义

按中序遍历左子树;

访问根;

按中序遍历右子树

proceduremake(t:

link);proceduremake(t:

intger);

beginbegin

ift<>nilthenift<>0then

beginbegin

make(t^.l);make(list[t].l)

访问t^.data访问list[t].data

make(t^.r);make(list[t].r);

end;end;

end;end;

(3)后序遍历DGEBHIFCA

递归定义

按后序遍历左子树;

按后序遍历右子树;

访问根

proceduremake(t:

link);proceduremake(t:

intger);

beginbegin

ift<>nilthenift<>0then

beginbegin

make(t^.l);make(list[t].l)

make(t^.r);make(list[t].r);

访问t^.data访问list[t].data

end;end;

end;end;

练习题

1.用顺序存储方式建立一棵深度为N(N<6)的满二叉树,并对其进行先序遍历。

(tree1.pas)

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

(tree2.pas)

3.如图所示的二叉树,按先序边历读入字符串ABC##DE#G##F###(其中#表示对应的指针为空格),试用链表存储方式建立二叉数,然后用中序边历输出。

(tree4.pas)

参考程序

【tree1.pas】

programtree1;

var

b:

array[1..31]ofchar;

e:

array[1..63]ofbyte;

n,h,i,k:

integer;

proceduretree(t:

integer);

begin

ife[t]=0thenexit

elsebegin

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;

fori:

=1tokdo

e[i]:

=1;

fori:

=1to26do

b[i]:

=chr(64+i);

fori:

=1to5do

b[26+i]:

=chr(48+i);

h:

=1;

tree(h);

writeln;

end.

【tree2.pas】

programtree2;

const{人工建立二叉树的链表关系}

a:

array[1..8]ofchar=('A','B','C','D','E','F','G','H');

r:

array[1..8]ofinteger=(3,5,0,0,0,8,0,0);

l:

array[1..8]ofinteger=(2,4,6,0,7,0,0,0);

var

e:

array[1..7]ofinteger;

proceduresearch(m:

integer);

begin

ife[m]=0thenbegin

write(a[m]);e[m]:

=1

end;

if(l[m]=0)and(r[m]=0)thenexit

elsebegin

ifl[m]<>0thensearch(l[m]);

ifr[m]<>0thensearch(r[m]);

end;

end;

begin

fillchar(e,sizeof(e),0);

search

(1);

writeln;

end.

【tree4.pas】仅给出建树过程

procedurecrt(varbt:

指针记录类型){按先序边历建树过程}

VAR....

Begin

Read(ch);

Ifch=’#’thenbt:

=nil

Else

New(bt);bt^.data:

=ch;{建根节点}

Crt(bt^.l);{建左子树}

Crt(bt^.r);{建右子树}

End;

6.二叉排序树

排序树T是一棵按中序已分类的二叉树,即对于树的每个节点(包括顶点),值比它小的那些节点都在它的左边,值比它大的的右边。

按中序遍历,即可得到各个节点的信息域(data)按从小到大顺序的序列。

如图是一棵二叉排序树:

7

3

11

15913

(1)下列过程是以tree为根的一棵排序二叉中插入一个信息域值为newdata的节点。

Procedureinsert(vartree:

link;newdata:

datatype);

Begin

Iftree=nilthen

Begin

New(tree);

Tree^.l:

=nil;tree^.r:

=nil;tree^.data:

=newdata;{插入新节点}

End

Else

Ifnewdata

Insert(tree^.l,newdata);{新节点插在左子树中,以tree^.l为子树继续寻找插入位置}

Else

Insert(tree^.r,newdata);{新节点插在右子树中,以tree^.r为子树继续寻找插入位置}

End;

主程序框架如下

vartemp:

datatype;{节点类型}

root:

link;{根}

begin

root:

=nil;

repeet

read(temp);

iftemp<>’#’then{#是结束标志}

insert(root,temp);

untiltemp=’#’

end.

(2)如何在一棵二叉排序树中找出具有关键字V的节点,我们可采用分割查找,程序如下:

procedurefind(t:

link;v:

datatype);

begin

ift=nilthen

begin

writeln(‘Notfind!

’);

exit;

end;

else

begin

ift^.data>vthenfind(t^.l);

elseift^.data

else

begin

writeln(‘find!

’);

exit;

end;

end;

end;

(3)练习题

.给出一组数据:

R={10.18,3,8,12,2,7,3},试编程序,先构造一棵二叉排序树,然后以中序遍历访问所得到的二叉树(即按数据域的值从小到大输出),并输出遍历结果。

(tree3.pas)

【tree3.pas】构造的二叉排序树如下

programtree3;

const

a:

array[1..8]ofinteger=(10,18,3,8,12,2,7,3);

type

point=^nod;

nod=record

w:

integer;

right,left:

point;

end;

var

first:

point;

j,k:

integer;

procedurehyt(d:

integer;varp:

point);

begin

ifp=nilthenbegin

new(p);

ifk=1thenbegin

first:

=p;

k:

=2

end;

withp^do

begin

w:

=d;

right:

=nil;

left:

=nil;

end;

end

else

withp^do

ifd>=wthenhyt(d,right)elsehyt(d,left);

end;

procedurehyt1(p:

point);

begin

withp^do

begin

ifleft<>nilthenhyt1(left);

write(w:

4);

ifright<>nilthenhyt1(right);

end

end;

begin

first:

=nil;

k:

=1;

forj:

=1to8dohyt(a[j],first);

hyt1(first);

writeln

end.

6.普通树转换成二叉树:

凡是兄弟就用线连起来,然后去掉父亲到儿子的连线,只留下父母到其第一个子女的连线。

AA

BCDB

EFGHIEC

普通树FD

GH

转换成二叉树I

 

四、例:

1.给出八枚金币a,b,c,d,e,f,g,h,编程以称最少的次数,判定它们蹭是否有假币,如果有,请找出这枚假币,并判定这枚假币是重了还是轻了。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1