1 / 93

数据结构

数据结构. 数据结构的概念. 表:学生档案. 数据结构的概念. 数据( data ): 凡是能输入到计算机的描述客观事物的符号 数据元素( data element ): 也叫结点( node )或记录( record ),是数据的基本单位。如:表中的一行就是一个数据元素。 数据项( data item ): 是数据不可分割的最小单位。如:“学号”、”数学“等。 数据对象( data object ): 指性质相同的数据元素的集合。如:所有的男生就构成一个数据对象。

baba
Download Presentation

数据结构

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 数据结构

  2. 数据结构的概念 表:学生档案

  3. 数据结构的概念 • 数据(data):凡是能输入到计算机的描述客观事物的符号 • 数据元素(data element):也叫结点(node)或记录(record),是数据的基本单位。如:表中的一行就是一个数据元素。 • 数据项(data item):是数据不可分割的最小单位。如:“学号”、”数学“等。 • 数据对象(data object):指性质相同的数据元素的集合。如:所有的男生就构成一个数据对象。 • 数据结构(data structure):数据之间的关系。包括数据的逻辑结构和数据的存储结构(物理结构)。

  4. 数据的逻辑结构 • 计算机所处理的数据一般都存在某种内在的、特殊的关系,这种数据本身以及它们内在的相互之间的逻辑关系,叫做数据的逻辑结构。 • 用一个二元组 B=(D,S) 表示。 D表示结点构成的集合 S表示D中结点之间关系的集合 包括初等类型和组合类型 • 整型 • 实型 • 布尔型 • 字符型 • 指针型 • 集合结构:数据元素之间除了同属于一个集合的关系外,无任何其它关系。 • 线性结构:数据元素之间存在一对一的线性关系。 • 树型结构:数据元素之间存在一对多的层次关系。 • 图结构:数据元素之间存在多对多的任意关系。

  5. 数据的存储结构 顺序存储(数组) • 表中一行(即一个学生信息)抽象成一个结点ai,ai与a(i+1)在存储上是相邻的。 • 设a1的起始地址为S,每个元素占M个存储单元(字节),则第i个元素的起始存储位置为 • loc(ai)=loc(a1)+(i-1)m

  6. 数据的存储结构 • 链式存储(指针)

  7. • 先进后出表(FILO)或下推表 • 假设栈的最大长度为m,所有结点都具有同一类型stype,则定义栈如下: Const m=栈的最大长度; Type stack=array[1..m] of stype; {栈类型} Var s:stack; {栈} t:integer; {栈顶指针} xx:stype; • 栈的基本运算: • 入栈 push • 出栈 pop • 读取栈顶元素 top

  8. 入栈 push(s,x,t) • 过程push(s,x,t)往栈S中压入一个值为X的结点。 Procedure push(var s:stack; x:stype; var t:integer;); Begin if t=m then writeln(‘full!’) else begin t:=t+1; s[t]:=x; end; End;

  9. 出栈 pop(s,t) • 函数pop(s,t)从栈s中弹出一个结点。 Function pop(var s:stack; var t:integer;):stype; Begin if t=0 then writeln(‘empty!’) else begin pop:=s[t]; t:=t-1; end; End; Procedure pop(var s:stack; var t:integer); Begin if t=0 then writeln(‘empty!’) else begin xx:=s[t]; t:=t-1; end; end;

  10. 读取栈顶元素 top(s,t) • 函数top(s,t)读栈顶元素。 Function top(s:stack; t:integer;):stype; Begin if t=0 then writeln(‘empty!) else top:=s[t]; End;

  11. 栈的应用 • 计算表达式的值 • 非递归的回溯法

  12. 计算表达式的值 • 输入一个表达式,该表达式含+、-、*、/、(、)和操作数,所含字符数不超过255,以@结束,输出该表达式的值。 • 分析:字符串输入,不能进行数值计算,所以,需要将输入的中缀表达式转换成后缀表达式。 输入字符串:e 后缀表达式:a 存放运算符的栈:s

  13. 计算表达式的值 当e[i]为: • 数字: e[i]压入a; • (: e[i]压入s; • ): 将s中栈顶至(间的所有运算符出栈进入a,丢弃(; • +、-: 将s中栈顶至(间的所有运算符出栈进入a, e[i]进入s; • *、/: 将s中栈顶至(前的第一个+或-前的所有运算符出栈进入a,e[i]压入s; • 例e:5 * 8 + 3 * ( 5 * 2 / 3 – 4 ) + 7 • 则a:5 8 * 3 5 2 * 3 / 4 - * + 7 +

  14. 队列 • 先进先出表(FIFO) • 插入的一端称为队尾r,删除的一端称为队首f f r f r f r

  15. 定义队列: Const m=队列元素的上限; Type equeue=array[1..m] of qtype; Var q:equeue; r,f:integer; • 初始:f=r=0 • 队满:r=m • 队空:f=r 队列的主要运算: • 入队(ADD) • 出队(DEL)

  16. 入队ADD(q,x,r) • 过程ADD(q,x,r)在队列q的尾端插入元素x Procedure ADD(var q:equeue; x:qtype; var r:integer;); Begin if r=m then writeln(‘full!’) else begin r:=r+1; q[r]:=x; end; End;

  17. 出队 DEL(q,y,f) • 过程DEL(q,y,f)取出q队列的队首元素y Procedure DEL(var q:equeue; var y:qtype; var f:integer;); Begin if f=r then writeln(‘empty’) else begin f:=f+1; y:=q[f]; end; End;

  18. 假溢出 • 随着队列一端插入,一端删除,队列在数组中不断向队尾方向移动,而在队首产生一片不以利用的空闲存储区,最后会导致当r=m时,不能再加入元素,形成假溢出。 r f r r f f f r 初始 加入3个元素 删除3个元素 加入m-3个元素,队满 f=r=0 f=0 r=3 f=r=3 r=m f=3

  19. 循环队列 • 初始:f=r=m • 入队:r:=r+1; r:=r mod m +1 if r=m+1 then r:=1; • 出队:f:=f+1; f:=f mod m +1 if f=m+1 then f:=1; • 队空:f=r; • 队满:f=r mod m+1; m m-1 f 3 2 r 1

  20. r a b c e f g h i j k 树 • 树的递归定义: • 有且仅有一个结点没有前驱(父结点),该结点为树的根 • 除根外,其余所有结点有且仅有一个前驱 • 除根外,每一个结点都通过唯一的路径连到根上 根结点 第一层 分支结点 第二层 第三层 叶结点 第四层

  21. • 结点的度=该结点的子树树目 • 树的度=max(所有结点的度) • 树的深度(高度)=树中最大的层次 • 森林:若干棵互不相交的树的集合 • 有序树和无序树

  22. 树的表示方法 • 自然界的树形表示法:用结点和边表示树 • 括号表示法:先将根结点放入一对()中,然后把它的子树按由左而右的顺序放入()中,而对子树也采用同样方法处理:同层子树放入它们根结点后面的()中,同层子树之间用逗号隔开: (r(a(e,f(j)),b(g),c(h(k),i)))

  23. 树的存储结构 • 静态记录数组 所有结点存储在一个数组中,数组元素为记录类型,包括数据域和长度为n(n为树的度)的数组,分别存储该结点的每一个儿子的下标。 Const n=树的度; max=结点数的上限; Type node=record data:datatype; ch:array[1..n]of integer; end; treetype=array[1..max] of node; Var tree:treetype;

  24. 树的存储结构 • 动态多重链表 每个结点由数据域和n(n为树的度)个指针域共n+1个域组成。 const n=树的度; Type treetype=^node; node=record data:datatype; next:array[1..n] of treetype; end; var root:treetype;

  25. 二叉树 • 二叉树的递归定义 • 二叉树是以结点为元素的有限集,它或者为空,或者满足以下条件: • 有一个特定的结点称为根; • 余下的结点分为互不相交的子集L和R,其中R是根的左子树,L是根的右子树,L和R又是一棵二叉树。 • 二叉树和树是两个不同的概念: • 树的每个结点可以有任意多个后继,而二叉树中每个结点的后继不能超过2; • 树的子树可以不分次序(有序树除外),而二叉树的子树有左右之分。

  26. a 空二叉树 b 只有一个结点的二叉树 c 只有左子树的二叉树 d 只有右子树的二叉树 e 左、右子树均有的二叉树 二叉树的形态 • 二叉树的五种基本形态

  27. 二叉树的两个特殊形态 • 满二叉树:一棵深度为K且有2K-1个结点的二叉树称为满二叉树 • 完全二叉树:如果一棵二叉树最多只有最下面两层结点度数可以小于2,并且最下面一层的结点都集中在该层最左边的若干位置上,则称此二叉树为完全二叉树。

  28. 二叉树的存储结构 • 顺序存储结构 Const m=树中结点数上限; Type node=record data:datatype; prt,lch,rch:0..m; end; Treetype=array[1.m]of node; Var tree:treetype;

  29. 二叉树的存储结构 • 链式存储结构 Type bitrpetr=^node; node=record data:datatype; lch,rch:bitrpetr; end; Var bt:bitreptr;

  30. a b c d e f g h i j l k 二叉树的遍历 • 前序:abdheicfjkgl • 中序:dhbeiajkfclg • 后序:hdiebkjflgca

  31. 前序遍历 • 二叉链表 Procedure preorder(bt:bitreptr); Begin if bt<>nil then begin 访问处理bt^.data; preorder(bt^.lch); preorder(bt^.rch); end; End; • 二叉树的顺序存储结构 • Procedure preorder(i:integer;); • Begin if i<>0 then • begin • 访问处理tree[i].data; • preorder(tree[i].lch); • preorder(tree[i].rch); • end; • End;

  32. 中序遍历 • 二叉链表 Procedure inorder(bt:bitreptr); Begin if bt<>nil then begin inorder(bt^.lch);访问处理bt^.data; inorder(bt^.rch); end; End; • 二叉树的顺序存储结构 • Procedure inorder(i:integer;); • Begin if i<>0 then • begin • inorder(tree[i].lch); • 访问处理tree[i].data; • inorder(tree[i].rch); • end; • End;

  33. 后序遍历 • 二叉链表 Procedure postorder(bt:bitreptr); Begin if bt<>nil then begin postorder(bt^.lch); postorder(bt^.rch); 访问处理bt^.data; end; End; • 二叉树的顺序存储结构 • Procedure inorder(i:integer;); • Begin if i<>0 then • begin • inorder(tree[i].lch); • inorder(tree[i].rch); • 访问处理tree[i].data; • end; • End;

  34. r a r r w b x a b c a b c f c d w f s t u x w f s t u x s h e d e i j d e i j i t h m o n h m o n m j u o n 普通有序树的遍历 • 普通树转换成二叉树 • 长子变左儿子 • 兄弟变右儿子

  35. r s t e a b f c d g t r s s t r e a d e a d b f b f c g c g 森林的遍历 • 森林转换成二叉树

  36. 由中序和后序确定前序 • 中序和后序确定前序 • 中序:s’=s1’……sk’……sn’ • 后序:s’’=s1’’…………sn’’ • 显然, sn’’为根,在前序中直接输出,设在中序中与sn’’相同的字符为sk’ • 若k>1,则左子树存在, s1’……sk-1’为左子树的中序遍历,s1’’……sk-1’’为左子树的后序遍历 • 若k<n,则右子树存在, sk+1’……sn’为右子树的中序遍历,sk’’……sn-1’’为右子树的后序遍历

  37. 由中序和后序确定前序 Procedure solve1(s1,s2:string); Var k:integer; Begin if length(s2)=1 then write(s2) {递归出口} else begin k:=pos(s2[length(s2)],s1); write(s1[k]); if k>1 then solve1(copy(s1,1,k-1),copy(s2,1,k-1)); if k<length(s1) then solve1(copy(s1,k+1,length(s1)-k),copy(s2,k,length(s2)-k)); end; End;

  38. 由中序和前序确定后序 Procedure solve2(s1,s2:string); Var k:integer; Begin if length(s2)=1 then write(s2) else begin k:=pos(s2[1],s1); if k>1 then solve2(copy(s1,1,k1),copy(s2,2,k)); if k<length(s1) then solve2(copy(s1,k+1,length(s1)-k), copy(s2,k+1,length(s2)-k)); end; End;

  39. 二叉树的应用 • 二叉排序树 • 最优二叉树

  40. 二叉排序树 • 二叉排序树是具有以下性质的非空二叉树: • 若根的左子树不空,则左子树的所有结点值均小于根结点值; • 若根的右子树不空,则右子树的所有结点值均不小于根结点值; • 根结点的左、右子树也分别为二叉排序树。 例:输入序列a1,a2……an(1<=n<=1000),将a按照递增顺序排列后输出。 • 构造二叉排序树的方法: • 令a1为二叉树的根; • 若a2<a1,则令a2为a1左子树的根结点,否则令a2为a1右子树的根结点; • 对a3,a4……an递归重复②。

  41. 构造二叉排序树 例:a序列为:35 40 30 90 82 32 33 37 35 30 40 32 37 90 33 82 中序遍历:30 32 33 35 37 40 82 90

  42. 构造二叉排序树 procedure createtree; begin fillchar(b,sizeof(b),0); b[1].data:=a[1]; for i:=2 to n do begin b[i].data:=a[i]; p:=1; while true do if a[i]<b[p].data then if b[p].l<>0 then p:=b[p].l else begin b[p].l:=i; break; end else if b[p].r<>0 then p:=b[p].r else begin b[p].r:=i; break; end; end; end; 稳定的

  43. 构造二叉排序树 • 主程序 Begin readln(n); for i:=1 to n do read(a[i]); writeln; createtree; inorder(1); End.

  44. <80 <60 <70 <90 不及格 <70 <60 中 良 优 及格 <80 不及格 及格 中 <90 良 优 最优二叉树 • 最优二叉树(哈夫曼树、最优搜索树) 例:计算最优的判定过程 全校学生的成绩由百分制转换成五等分制,在五个等级上分布不均匀,颁布规律如下: 百分制分数范围 0~59 60~69 70~79 80~89 90~100 分布情况% 5 15 40 30 10 现有10000个数据,以下两种判定转化过程: K1=10000*(1*5%+2*15%+3*40%+4*(30%+10%))=31500 K2=10000*(2*(40%+30%+10%)+3*(5%+15%))=22000

  45. 最优二叉树 • 结点的路径长度:从根到每个结点的路径长度 • 叶结点的权值:叶结点被赋予的实数值 • 设Wk为第k个结点的权值,Pk为第k个叶结点的带权路径长度。 L=W1*P1+W2*P2……Wn*Pn 则使L最小的树称为最优二叉树。

  46. 24 7 5 2 4 6 24 A B C D E 6 7 5 6 13 11 A B E 6 A E B 7 6 5 7 6 11 13 11 C D A E 2 4 构造最优二叉树 • 构造方法: • 将给定的N个结点构成N棵二叉树的集合F,其中每棵二叉树Ti中只有一个权值为Wi的根结点Ki,其左右、子树均为空; • 在F中选取根结点权值最小的两棵二叉树作为左、右子树,构造一棵新的二叉树,并且置新的二叉树的根结点的权值为其左、右子树根结点的权值之和; • 在F中删除这两棵二叉树,同时将新得到的二叉树加入F中; • 重复②③,直到在F中只含有一棵二叉树为止。

  47. 最优二叉树 • 最优二叉树中非叶子结点的度均为2 • 如果叶结点数为N,则总结点数为2*N-1 Const n=叶结点的上限; m=2*n-1; Type node=record data:integer; prt,lch,rch,lth:0..m; end; wtype=array[1..n] of integer; treetype=array[1..m] of node; {tree[1..n]为叶子结点, tree[n+1..2*n-2]为分支结点,tree[2*n-1]为根} Var tree:treetype;

  48. 构造最优二叉树 Procedure hufm(w:wtype;var tree; var bt:integer); function min(h:integer):integer; begin m1:=maxint; for p:=1 to h do if (tree[p].prt=0) and (m1>tree[p].data) then begin i:=p; m1:= tree[p].data; end; min:=i; end; Begin fillchar(tree,sizeof(tree),0); for i:=1 to n do read(tree[i].data); for k:=n+1 to m do begin i:=min(k-1); tree[i].prt:=k; tree[k].lch:=i; j:=min(k-1); tree[j].prt:=k; tree[k].rch:=j; tree[k].data:=tree[i].data+tree[j].data; end; bt:=m; End;

  49. 求最优判断 Procedure ht(t:integer); {通过前序遍历计算每个叶子的路径长度} Begin if t=m then tree[t].lth:=0 else tree[t].lth:=tree[tree[t].prt].lth+1 if tree[t].lth<>0 then begin ht(tree[t].lch); ht(tree[t].rch); end; End; BEGIN readln(n); for i:=1 to 5 do readln(w[i]); hufm(w,tree,bt); ht(bt); writlen(m*tree[bt].data); for i:=1 to 5 do write(n*tree[i].lth*tree[i].data:0:0); END.

  50. • 图是较线性表和树更为复杂的一种数据结构,在这种数据结构中,数据结点间的联系是任意的,因此它可以更广泛地表示数据元素之间的关系。 • 线性表和树是图的特例。

More Related