1、第1章绪论 内容提要: 数据结构研究的内容。 针对非数值计算的程序设计问题,研究计算机的操作对象以及它们之间的 关系和操作。 数据结构涵盖的内容: 钱进结构(建性表、栈、駄、串、数纽 駅除运翳 修改运算 查找运算 排序运算 基本概念:数据、数据元素、数据对象、数据结构、数据类型、抽象数据类型。 数据一一所有能被计算机识别、 存储和处理的符号的集合。 数据元素一一是数据的基本单位,具有完整确定的实际意义。 数据对象一一具有相同性质的数据元素的集合,是数据的一个子集。 数据结构是相互之间存在一种或多种特定关系的数据元素的集合,表示为: Data_Structure=(D, R) 数据类型一一是一个
2、值的集合和定义在该值上的一组操作的总称。 抽象数据类型一一由用户定义的一个数学模型与定义在该模型上的一组操作, 它由基本的数据类型构成。 算法的定义及五个特征。 算法 是对特定问题求解步骤的一种描述,它是指令的有限序列, 是一系列输入转换为输 出的计算步骤。 算法的基本特性:输入、输出、有穷性、确定性、可行性 算法设计要求。 1正确性、可读性、健壮性、效率与低存储量需求 算法分析。 时间复杂度、空间复杂度、稳定性 学习重点: 数据结构的“三要素”:逻辑结构、物理(存储)结构 及在这种结构上所定义的操作(运 算)。 用计算语句频度来估算算法的时间复杂度。 非线性结掏 树结构 图结构 数据结构物理
3、()结杓 鞭疼结构 遂式结构 紊引结构 散列结构 插入运算 第二章线性表 内容提要: 线性表的逻辑结构定义,对线性表定义的操作。 线性表的定义:用数据元素的有限序列表示 丿- n为元素兑 口时称为空眈曽:器 线性表的存储结构:顺序存储结构和链式存储结构。 顺序存储定义:把逻辑上 相邻的数据元素存储在物理上 相邻的存储单元中的存储结构。 链式存储结构:其结点 在存储器中的位置是随意的, 即逻辑上相邻的数据元素在物理上 定相邻。通过指针来实现! 线性表的操作在两种存储结构中的实现。 数据结构的基本运算:修改、插入、删除、查找、排序 1)修改一一通过数组的下标便可访问某个特定元素并修改之。 核心语句
4、:Vi=x; 顺序表修改操作的时间效率是0(1) 2)插入在线性表的第i个位置前插入一个元素 实现步骤: 1将第n至第i位的元素向后移动一个位置; 2将要插入的元素写到第i个位置; 3表长加1。 注意:事先应判断:插入位置i是否合法?表是否已满? 应当符合条件:K i=i; j-) aj+1=a j ; a i =x; n+; 插入时的平均移动次数为:n(n+1)/2*(n+1) =n/20(n) 3)删除一一删除线性表的第i个位置上的元素 实现步骤: 1将第i+1至第n位的元素向前移动一个位置; 2表长减1。 注意:事先需要判断,删除位置i是否合法? 应当符合条件:K in或i=1, n 核
5、心语句: for ( j=i+1; j=n; j+ ) aj-1=aj; n-; 不一 顺序表删除一元素的时间效率为:T(n)=(n-1)/2疋0(n) 顺序表插入、删除算法的平均空间复杂度为0(1) 单链表: #in clude #in clude typedef struct node char data; struct node *n ext; n ode; node *p,*q,*head; int n ; int m=sizeof( no de); 一般需要3个指针变量 /数据元素的个数 /*结构类型定义好之后,每个node类型的长度就固定了, m求一次即可*/ void build
6、()/字母链表的生成。要一个个慢慢链入 prin tf(%c,p-data); p=p-n ext; 用单链表结构来存放26个英文字母组成的线性表(a,b,c,,,z),请写出C语言程序。 int i; head=(no de*)malloc(m); p=head; for( i=1; idata=i+a-1; p-next=(no de*)malloc(m); p=p-next; p-data=i+ a-1; p- next=NULL ; void display() p=head; while (p) /m=sizeof( no de)前面已求出 因尾结点要特殊处理,故iz26 /第一个结
7、点值为字符a /为后继结点“挖坑” ! /让指针变量P指向后一个结点 最后一个元素要单独处理 /单链表尾结点的指针域要置空! 字母链表的输出 /当指针不空时循环(仅限于无头结点的情况) 让指针不断“顺藤摸瓜” (2)单链表的修改(或读取) 思路:要修改第i个数据元素,必须从头指针起一直找到该结点的指针p, 然后才能:pdata=n ew_value 读取第i个数据元素的核心语句是: Linklist *find(Linklist *head ,int i) int j=1; Li nklist *p; P=head-n ext; While(p!=NULL) j+; return p; 3单链
8、表的插入 兹结点的生成方式土S= (node*) ma I loc (m); S-next=p-nex t 链表插入的核心语句: Step 1:s-next=p-next; Step 2:p-next=s; 6单链表的删除 删除动作的核心语句(要借助辅助指针变量q): q = p-next;/首先保存b的指针,靠它才能找到c; p-next=q-next;将a、c两结点相连,淘汰b结点; free(q);彻底释放b结点空间 7双向链表的插入操作: 二3i-g 口 IL:二 X 1 设p已指向第i元素,请在第i元素前插入元素x: 1ai-1的后继从ai (指针是p)变为x(指针是s): s_n
9、ext = p ;p-prior- next = s ; 2ai的前驱从ai-1 (指针是p-prior)变为x (指针是s); s-prior = p -prior ; p-prior = s ; 设p指向第i个元素,删除第i个 元素 后继方向:ai-1的后继由ai (指针p)变为ai+1(指针p -next ); p -prior- next =p_n ext 前驱方向:ai+1的前驱由ai (指针p)变为ai-1 (指针p - prior ); p-n ext-prior = p -prior ; 数组的逻辑结构定义及存储 数组:由一组名字相冋、下标不冋的变量构成 N维数组的特点:n个下
10、标,每个元素受到n个关系约束 一个n维数组可以看成是 由若干个n-1维数组 组成的线性表。 存储:事先约定按某种次序将数组元素排成一列序 列,然后将这个线性序列存入存储器中。 在二维数组中,我们既可以规定按行存储,也可以规定按列存储。 设一般的二维数组是Ac1.d1, c2.d2, 则行优先存储时的地址公式为: LOC(aij)=LOC(afb C2)+(i-c1)*(drc2+l)+j-c2) *L 二维数组列优先存储的通式为: LOC(现戸LOCQi口田(j弋尸(血7十1)和-门)江 稀疏矩阵(含特殊矩阵)的存储及运算。 稀疏矩阵:矩阵中非零元素的个数较少(一般小于5%) 学习重点: 线性
11、表的逻辑结构,指线性表的数据元素间存在着 线性关系。在顺序存储结构中,元素 存储的先后位置反映出这种 线性关系,而在链式存储结构中,是靠 指针来反映这种关系的。 顺序存储结构用一维数组表示,给定下标,可以存取相应元素,属于随机存取的存储结 构。 链表操作中应注意不要使链意外“断开”。因此,若在某结点前插入一个元素,或删除 某元素,必须知道该元素的 前驱结点的指针。 掌握通过画出结点图来进行链表(单链表、循环链表等)的生成、插入、删除、遍历 等 操作。 数组(主要是二维)在以 行序/列序为主的存储中的地址计算方法。 稀疏矩阵的三元组表存储结构。 稀疏矩阵的十字链表存储方法。 8.双向链表的删除操
12、作: Amu 加皿亦我 担日 1 世 补充重点: 1.每个存储结点都包含两部分: 数据域和指针域( (链域) 2.在单链表中,除了首元结点外,任一结点的存储位置由 3.在链表中设置头结点有什么好处? 头结点即在链表的首元结点之前附设的一个结点, 表长度等附加 信息,其作用是为了对链表进行操作时, 元结点进行统一处理,编程更 方便。 4.如何表示空表? (1)无头结点时,当头指针的值为空时表示空表; (2)有头结点时,当头结点的指针域为空时表示空表。 5.链表的数据元素有两个域,不再是简单数据类型,编程时该如何表示? 因每个结点至少有两个分量,且数据类型通常不一致,所以要采用结构数据类型。 6.
13、 sizeof(x)-计算变量x的长度(字节数); malloc(m) 开辟m字节长度的地址空间,并返回这段空间的首地址; free(p)-释放指针p所指变量的存储空间,即彻底删除一个变量。 7.链表的运算效率分析: (1)查找 因线性链表只能顺序存取,即在查找时要从头指针找起,查找的时间复杂度为O( n)。 (2)插入和删除 因线性链表不需要移动元素,只要修改指针,一般情况下时间复杂度为O(1)。 但是,如果要在单链表中进行前插或删除操作,因为要从头查找前驱结点,所耗时间复杂 度将是O(n)。 例:在n个结点的单链表中要删除已知结点*P,需找到它的前驱结点的地址,其时间复杂 度为O(n) 8
14、.顺序存储和链式存储的区别和优缺点? 顺序存储时,逻辑上相邻的数据元素,其物理存放地址也相邻。顺序存储的优点是存储 密度大,存储空间利用 率高;缺点是插入或删除元素时不方便。 链式存储时,相邻数据元素可随意存放,但所占存储空间分两部分, 一部分存放结点值, 另一部分存放表示结点间关系的指针。链式存储的优点是插入或删除元素时很方便,使用 灵活。缺点是存储密度小,存储空间利用率低。 顺序表适宜于做查找这样的静态操作; 链表宜于做插入、删除这样的动态操作。 若线性表的长度变化不大,且其主要操作是查找,则采用顺序表; 若线性表的长度变化较大,且其主要操作是插入、删除操作,则采用链表。 9.判断:“数组
15、的处理比其它复杂的结构要简单”,对吗? 答:对的。因为一一 1数组中各元素具有统一的类型; 2数组元素的下标一般具有 固定的上界和下界,即数组一旦被定义,它的维数和维界就不 再改变。 3数组的基本操作比较简单,除了结构的初始化和销毁之外,只有存取元素和修改元素值的 操作。 10.三元素组表中的每个结点对应于稀疏矩阵的一个非零元素,它包含有三个数据项,分别 表示该元素的行下标、列下标和元素值。 其直接前驱结点的链域的值指示。 该结点的数据域可以为空,也可存放 可以对空 表、非空表的情况以及对首 11.写出右图所示稀疏矩阵的压缩存储形式。 解:介绍3种存储形式。 法1:用线性表表示: (1,2,1
16、2),(1,3,9),(3,1,-3),(3,5,14), (4,3,24),(5,2,18),(6,1,15),(6,4,-7) 法2:用十字链表表示 用途:方便稀疏矩阵的加减运算 方法:每个非0元素占用5个域 和显示该表的C语言程序。 char V30; void build()字母线性表的生成,即建表操作 int i; V0=a; for( i=1;i=n-1;i+ ) Vi=Vi-1+1; void display( ) /字母线性表的显示,即读表操作 int i; for( i=0;iM)上溢 else stop+=e; 顺序栈出栈函数POP() status Pop() if(to
17、p=L) 下溢 else e=s-top; return(e); 队列的定义及操作,队列的删除在一端(队尾),而插入则在队列的另一端(队头)。因 此在两种存储结构中,都需要队头和队尾两个指针。 队列:只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表。 链队列 结点类型定义: typedef Struct QNode QEIemTypedata;/元素 Struct QNode*n ext; /指向下一结点的指针 Qnode , * QueuePtr ; 链队列类型定义: typedef struct QueuePtrfront ; /队首指针 QueuePtrrear ; /队尾指
18、针 Lin kQueue; 链队示意图: i*ca I from Jl 旦 1空链队的特征:fron t=rear 2链队会满吗? 一般不会,因为删除时有free动作。除非内存不足! 3入队(尾部插入):rear-next=S; rear=S; 出队(头部删除):front-next=p-next; 2顺序队 顺序队类型定义: Vtifrt吗弓 fron, 空臥列的待征?I 約定:frait rrar 臥列会満吗?概易装 瞒I因为昨筑|常有怅度 限制,而英前 端空何盂辭放。 虫样实现人臥和也肌;提作T權右谐 句如下:| 入:rear*+ .Qrrar|-c; #defi neQUEUE-MAX
19、SIZE100 /最大队列长度 typedef struct QEIemType *base; int int SqQueue 建队核心语句: /队列的基址 front;/队首指针 rear;/队尾指针 q . base=(QEIemType *)malloc(sizeof (QEIemType * QUEUE_MAXSIZE; 顺序队示意图: /分配空间 0 aj ai 型 3i. 财 i 再A賦 rear 3 宙 出甌头曲删臨;rtK. e-Q ho nl|; 循环队列: 队空条件:front = rear(初始化时:front = rear ) 队满条件:front = (rear+1)
20、 % N(N=maxsize) 队列长度(即数据元素个数):L=(N+rear-front)% N 1)初始化一个空队列 StatusInitQueue ( SqQueue/分配空间 if (!q.base) exit(OVERFLOW);/内存分配失败,退出程序 q.front =q.rear=0; /置空队歹U return OK; /Ini tQueue; 2)入队操作 Status En Queue(SqQueue /队满则上溢,无法再入队 q.rear = ( q . rear + 1 ) % QUEUE_MAXSIZE; q.base q.rear = e;/新元素e入队 retu
21、rn OK; / En Queue; 3)出队操作 Status DeQueue ( SqQueue /队列空 q.fron t=(q.fro nt+1) % QUEUE_MAXSIZE ; e = q.base q.front ; return OK; / DeQueue 链队列空的条件是首尾指针相等,而循环队列满的条件的判定,则有队尾加 和设标记两种方法。1等于队头 补充重点: 1.为什么要设计堆栈?它有什么独特用途? 1调用函数或子程序非它莫属; 2递归运算的有力工具; 3用于保护现场和恢复现场; 4简化了程序设计的问题。 2.为什么要设计队列?它有什么独特用途? 1离散事件的模拟(模拟
22、事件发生的先后顺序,例如CPU芯片中的指令译码队列); 2操作系统中的作业调度(一个CPU执行多个作业); 3简化程序设计。 3.什么叫“假溢出”?如何解决? 答:在顺序队中,当尾指针已经到了数组的上界,不能再有入队操作, 但其实数组中还有空 位置,这就叫“假溢出”。解决假溢出的途径-采用循环队列。 4.在一个循环队列中,若约定队首指针指向队首元素的前一个位置。那么,从循环队列中删 除一个元素时,其操作是先移动队首位置,后取出元素。 5.线性表、栈、队的异同点: 相同点:逻辑结构相同, 都是线性的;都可以用顺序存储或链表存储;栈和队列是两种特殊 的线性表,即受限的线性表(只是对插入、删除运算加
23、以限制)。 不同点:运算规则不同: 线性表为随机存取; 而栈是只允许在一端进行插入和删除运算,因而是后进先出表LIFO; 队列是只允许在一端进行插入、另一端进行删除运算,因而是先进先出表FIFO。 用途不同,线性表比较通用;堆栈用于函数调用、递归和简化设计等;队列用于离散事 件模拟、OS作业调度和 简化设计等。 第四章串 内容提要: 串是数据元素为字符的线性表,串的定义及操作。 串即字符串,是由零个或多个字符组成的有限序列,是数据元素为单个字符的特殊线性表。 串比较:int strcmp(char *s1,char *s2); 求串长:int strle n( char *s); 串连接:ch
24、ar strcat(char *to,char *from) 子串T定位:char strchr(char *s,char *c); 串的存储结构,因串是数据元素为字符的线性表,所以存在“结点大小”的问题。 模式匹配算法。 串有三种机内表示方法: 耐用一组地址连续的存储单元存储串垃的字 存诸称序列,属ifr态存储方式. 堆令少存储表示 -用-组连续的存储单元存储串垃的字 符序列,但存瞎空同是在稈序执祎过程中彩 継吉 分配而得* 鹫誇串的块雒捽储表示 仔临链式方式存储 模式匹配算法: 算法目的:确定主串中所含子串第一次出现的位置(定位) 定位问题称为串的模式匹配,典型函数为In dex(S,T,
25、pos) BF算法的实现一即编写Index(S, T, pos)函数 BF算法设计思想: 将主串S的第pos个字符和模式T的第1个字符比较, 若相等,继续逐个比较后续字符; 若不等,从主串S的下一字符(pos+1)起,重新与T第一个字符比较。 直到主串S的一个连续子串字符序列与模式T相等。返回值为S中与T匹配的子序列 第一个字符的序号,即匹配成功。 否则,匹配失败,返回值0。 Int In dex_BP(SStri ng S, SStri ng T, i nt pos) /返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0. 其中,T非空,1poswStrLength(S)
26、i=pos; j=1; while ( i=S0 /T子串指针j正常到尾,说明匹配成功,else return 0;/ 否则属于iS0情况,i先到尾就不正常 /I ndex_BP 补充重点: 1.空串和空白串有无区别? 答:有区别。 空串(Null String)是指长度为零的串; 而空白串(Blank String),是指包含一个或多个空白字符 2.“空串是任意串的子串;任意串S都是S本身的子串, (空格键)的字符串 S本身外,S的其他子串称为S 的真子串。 f运建吉枪s =* uiju.a* 定长顺序存储结构 串 T 有储齬构-堆存情结构 二若干函数的实现 1 模式匹配算法 模式匹配即子串
27、定位运算即如何实现lDd0)结点组成的有限集合T,有且仅有一个结点称为根(root),当n1时,其余的结点分为m (m0)个互不相交的有限集合T1,T2,Tm。每个集合本身又是 棵树,被称作这个根的子树。 二叉树:是n(n0)个结点的有限集合,由一个根结点以及两棵互不相交的、分别称为左 子树和右子树的二叉树 组成。 术语:P88 二叉树的性质,存储结构。 性质1:在二叉树的第i层上至多有2i-1个结点(i0)。 性质2:深度为k的二叉树至多有2k-1个结点(k0)。 性质3:对于任何一棵二叉树,若2度的结点数有n2个,则叶子数(n0)必定为n2+1性质4:具有n个结点 的完全二叉树的深度必为
28、_ 性质5:对完全二叉树,若从上至下、从左至右编号,则编号为i的结点,其左孩子编号必 为2i,其右孩子编号为2i+1;其双亲的编号必为i/2(i=1时为根,除外)。 二叉树的存储结构: 一、 顺序存储结构 按二叉树的结点“自上而下、 从左至右”编号, 用一组连续的存储单元存储。若是完全/满二叉树则可以做到唯一复原。 不是完全二叉树:一律转为完全二叉树! 方法很简单,将各层空缺处统统补上“虚结点”,其内容为空。 缺点:浪费空间;插入、删除不便 二、 链式存储结构 用二叉链表即可方便表示。一般从根结点开始存储。 irlt Cbtdngbt (hldd 优点:不浪费空间;插入、删除方便 二叉树的遍历
29、。 指按照某种次序访问二叉树的所有结点,并且每个结点仅访问一次,得到一个线性序列。 遍历规则 二叉树由根、左子树、右子树构成,定义为D、L、R 若限定先左后右,则有三种实现方案: LRD 后序遍历 DLR 先序遍历 LDR 中序遍历 树的存储结构,树、森林的遍历及和二叉树的相互转换。 1先序遍历 若森林为空,返回; 访问森林中第一棵树的根结点; 先根遍历第一棵树的根结点的子树森林; 先根遍历除去第一棵树之后剩余的树构成的森林。 2中序遍历 若森林为空,返回; 中根遍历森林中第一棵树的根结点的子树森林; 访问第一棵树的根结点; 中根遍历除去第一棵树之后剩余的树构成的森林。 回顾2:二叉树怎样还原
30、为树? 要点:逆操作,把所有右孩子变为兄弟! 讨论1:森林如何转为二叉树? 法一: 各森林先各自转为二叉树;依次连到前一个二叉树的右子树上。 法二:森林直接变兄弟,再转为二叉树 讨论2:二叉树如何还原为森林? 要点:把最右边的子树变为森林,其余右子树变为兄弟 树和森林的存储方式: 树有三种常用存储方式: 1双亲表示法孩子表示法孩子一兄弟表示法 问:树T二叉树的“连线一抹线一旋转”如何由计算机自动实现? 答:用“左孩子右兄弟”表示法来存储即可。 存储的过程就是树转换为二叉树的过程! 树、森林的遍历: 探度优先第历(先脈怎和 需驚蹩?皿 1广度忧去遁历(层执】 1先根遍历:访问根结点;依次先根遍历
31、根结点的每棵子树。 2后根遍历:依次后根遍历根结点的每棵子树;访问根结点。 讨论: 树若采用“先转换,后遍历”方式,结果是否一样? 1.树的先根遍历与二叉树的先序遍历相同; 2.树的后根遍历相当于二叉树的中序遍历; 3.树没有中序遍历,因为子树无左右之分。 淼林的逼历- 深度优先遍历先序、申序) 广度优先遍历层次1 二叉树的应用:哈夫曼树和哈夫曼编码。 Huffman树:最优二叉树(带权路径长度最短的树) Huffman编码:不等长编码。 n 树的带权路径长度:(树中所有叶子结点的带权路径长度之和) 构造Huffman树的基本思想:权值大的结点用短路 径,权值小的结点用长路径。 构造Huffm
32、an树的步骤(即Huffman算法): (1)由给定的n个权值 w1, w2, , , wn 构成n棵二叉树的集合F = T1, T2, , , Tn (即 森林),其中每棵 二叉树Ti中只有一个带权为wi的根结点,其左右子树均空。 (2)在F中选取两棵根结点权值最小的树 做为左右子树构造一棵 新的二叉树,且让新二叉 树根结点的权值等于其左右子树的根结点权值之和。 在F中删去这两棵树,同时将新得到的二叉树加入F中。 重复和,直到F只含一棵树为止。这棵树便是Huffman树。 具体操作步骤: stepl:对权值进行合并、删除与替换 在权値東合忡,5t2, 4中,总是合井当的最小的两个权 Huff
33、inan編码结果:d=:, i=ta- 0, n= WFL=lbitX7+2MtX5+3bitQ+4)=35 (小于尊长码的ffFL=36) 学习重点:(本章内容是本课程的重点) 二叉树性质及证明方法,并能把这种方法推广到K叉树。 二叉树遍历,遍历是基础,由此导出许多实用的算法,如求二叉树的高度、各结点的层 次数、度为0、1、2的结点 数。 由二叉树遍历的前序和中序序列或后序和中序序列可以唯一构造一棵二叉树。由前序和 后序序列不能唯一确定一棵 二叉树。 a.初始令并国同 FH7K11 吐合井(11 Ft 11 step2:按左“(T 右F 对 Htlffman 树的所有分支编号 将Huffma
34、n树与Huffman码挂钩 完全二叉树的性质。 树、森林和二叉树间的相互转换。 哈夫曼树的定义、构造及求哈夫曼编码。 补充: 1.满二叉树和完全二叉树有什么区别? 答:满二叉树是叶子一个也不少的树,而完全二叉树虽然前k-1层是满的,但最底层却允许 在右边缺少连续若干个结点。满二叉树是完全二叉树的一个特例。 2. Huffman树有什么用? 最小冗余编码、信息高效传输 第七章图 内容提要: 图的定义,概念、术语及基本操作。 图:记为G=( V, E ) 其中:V是G的顶点集合,是有穷非空集; E是G的边集合,是有穷集。 术语:见课件 图的存储结构。 1邻接矩阵(数组)表示法 1建立一个顶点表和一
35、个邻接矩阵 2设图A = (V, E)有n个顶点,则图的邻接矩阵是一个二维数组A.Edgenn。 注:在有向图的邻接矩阵中, 第i行含义:以结点vi为尾的弧(即出度边); 第i列含义:以结点vi为头的弧(即入度边)。 邻接矩阵法优点:容易实现图的操作,如:求某顶点的度、判断顶点之间是否有边(弧) 找顶点的邻接点等等。 邻接矩阵法缺点:n个顶点需要n*n个单元存储边(弧);空间效率为0(n2)。 2邻接表(链式)表示法 1对每个顶点vi建立一个单链表,把与vi有关联的边的信息(即度或出度边)链接起来, 表中每个结点都设为3 个域: 头站点表蛤点 2每个单链表还应当附设一个头结点(设为2个域),存
36、vi信息; 3每个单链表的头结点另外用顺序存储结构存储。 邻接表的优点:空间效率高;容易寻找顶点的邻接点; 邻接表的缺点:判断两顶点间是否有边或弧,需搜索两结点对应的单链表,没有邻接矩阵方 便。 图的遍历。 遍历定义:从已给的连通图中某一顶点出发,沿着一些边,访遍图中所有的顶点,且使 每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算。 图常用的遍历:一、深度优先搜索;二、广度优先搜索 深度优先搜索(遍历)步骤: 1访问起始点v; 2若v的第1个邻接点没访问过,深度遍历此邻接点; 3若当前邻接点已访问过,再找v的第2个邻接点重新遍历。 基本思想:一一仿树的先序遍历过程。 广度优先搜索(遍历
37、)步骤: 1在访问了起始点v之后,依次访问v的邻接点; 2然后再依次(顺序)访问这些点(下一层)中未被访问过的邻接点; 3直到所有顶点都被访问过为止。 图的应用(最小生成树,最短路经) 最小生成树(MST)的性质如下:若U集是V的一个非空子集,若(u0, v0)是一条最小 权值的边,其中uO U,v0 V-U;则:(u0, v0)必在最小生成树上。 求MST最常用的是以下两种:Kruskal(克鲁斯卡尔)算法、Prim(普里姆)算法 Kruskal算法特点:将边归并,适于求稀疏网的最小生成树。 Prime算法特点:将顶点归并,与边数无关,适于稠密网。 Kruskal法示刚:对边操作*旧井边普利
38、姆(Prim)算法示例:归井顶点 在带权有向图中A点(源点)到达B点(终点)的多条路径中,寻找一条各边权值之和最 小的路径,即最短路径。 两种常见的最短路径问题: 一、单源最短路径一用Dijkstra(迪杰斯特拉)算法 二、 所有顶点间的最短路径一用Floyd(弗洛伊德)算法 一、 单源最短路径(Dijkstra算法)一顶点到其余各顶点(vOTj) 目的: 设一有向图G=(V, E),已知各边的权值,以某指定点vO为源点,求从vO到 图的其余各点的最短路径。限定各边上的权值大于或等于0。 二、 所有顶点之间的最短路径 可以通过调用n次Dijkstra算法来完成,还有更简单的一个算法:Floyd
39、算法(自学)。 学习重点:图是应用最广泛的一种数据结构,本章也是这门课程的重点。 基本概念中,连通分量,生成树,邻接点是重点。 1连通图:在无向图中,若从顶点v1到顶点v2有路径,则称顶点v1与v2是连通的。 如果图中任意一对顶 点都是连通的,则称此图是连通图。 非连通图的极大连通子图叫做 连通分量。 2生成树:是一个极小连通子图,它含有图中全部n个顶点,但只有n-1条边。 3邻接点:若(u, v)是E(G)中的一条边,则称u与v互为邻接顶点。 图是复杂的数据结构,也有顺序和链式两种存储结构:数组表示法(重点是邻接距阵) 和邻接表。这两种存储结构对 有向图和无向图均适用 图的遍历是图的各种算法
40、的基础,应熟练掌握图的深度、广度优先遍历。 连通图的最小生成树不是唯一的,但最小生成树边上的权值之和是唯一的。 握prim和kruscal算法,_ 应熟练掌 从单源点到其他顶点,以及各个顶点间的最短路径问题,掌握熟练手工模拟。 补充: 1.问:当有向图中仅1个顶点的入度为0,其余顶点的入度均为1,此时是何形状? 答:是树!而且是一棵有向树! 2.讨论:邻接表与邻接矩阵有什么异同之处? 1.联系:邻接表中每个链表对应于邻接矩阵中的一行, 链表中结点个数等于一行中非零元素的个数。 2.区别: 对于任一确定的无向图,邻接矩阵是唯一的(行列号与顶点编号一致), 但邻接表不唯一(链接次序与顶点编号无关)
41、。 3.用途: 邻接矩阵多用于稠密图的存储 而邻接表多用于稀疏图的存储 3.若对连通图进行遍历,得到的是生成树 若对非连通图进行遍历,得到的是生成森林。 第八章 查找 内容提要: 查找表是称为集合的数据结构。是元素间约束力最差的数据结构:元素间的关系是元素 仅共在同一个集合中。(同 一类型的数据元素构成的集合) 查找表的操作:查找,插入,删除。 静态查找表:顺序表,有序表等。 针对静态查找表的查找算法主要有:顺序查找、折半查找、分块查找 一、 顺序查找(线性查找) 技巧:把待查关键字key存入表头或表尾(俗称“哨兵”),这样可以加快执行速度。 int Search_Seq( SSTable S
42、T , KeyType key ) ST.elemO.key =key; for( i=ST.le ngth; ST.elem i .key!=key;- - i ); return i; / Search_Seq /ASL=(1+n)/2,时间效率为0(n),这是查找成功的情况:顺序查找的特点: 优点:算法简单,且对顺序结构或链表结构均适用。 缺点:ASL太大,时间效率太低。 二、 折半查找(二分或对分查找) 若关键字不在表中,怎样得知并及时停止查找? 典型标志是:当查找范围的上界w下界时停止查找。 ASL的含义是“平均每个数据的查找时间”,而前式是n个数据查找时间的总和,所以: ASL j
43、 2jlog2(n 1) 1:log2n nj二n 三、分块查找(索引顺序查找) 思路:先让数据分块有序,即分成若干子表,要求每个子表中的数据元素值都比后一块中的 数值小(但子表内部未必 有序)。然后将各子表中的最大关键字构成一个索引表,表中还要 包含每个子表的起始地址(即头指针)。 特点:块间有序,块内无序。 查找:块间折半,块内线性 查找步骤分两步进行: 1对索引表使用折半查找法(因为索引表是有序表); 2确定了待查关键字所在的子表后,在子表内采用顺序查找法 (因为各子表内部是无序表) 查找效率ASL分析: ASLsU+L _ -B 对盍引表査推的|_ 对块内査找胯氏$1 址加=+ - 佃
44、“岂丿抵 M .) -._ _ _ 3希毎块内課的吐貿晞叩块的茹目二) 创即当n-叫5=33 Jr分快法的 殂折半佚要預 一先全 排序肝 爲时何. 枫.=3. 5而折半迭的开日1噸玮法咖L珂L+nW 动态查找表:二叉排序树,平衡二叉树。 特点:表结构在查找过程中动态生成。 要求:对于给定值key,若表中存在其关键字等于key的记录,则查找成功返回;否则插入 关键字等于key的记录。 1二叉排序树的定义 -或是一棵空树;或者是具有如下性质的非空二叉树: (1)左子树的所有结点均小于根的值; (2)右子树的所有结点均大于根的值; (3)它的左右子树也分别为二叉排序树。 2二叉排序树的插入与删除 思
45、路:查找不成功,生成一个新结点s,插入到二叉排序树中;查找成功则返回。 SearchBST (K, p为查找过程中进行扫描的指针 while(p!=NULL) case K= p-data:查找成功,return Kdata : q=p;p=p-L_child /继续向左搜索 K p-data : q=p;p=p-R_child /继续向右搜索 查找不成功则插入到二叉排序树中 s =(BiTree)malloc(sizeof(BiTNode); s-data=K; s -L_child=NULL; s -R_child=NULL; /查找不成功,生成一个新结点s,插入到二叉排序树叶子处 cas
46、e t=NULL:t=s; /若t为空,则插入的结点s作为根结点 K data:q-L_child=s; /若K比叶子小,挂左边 K q-data:q-R_child=s; /若K比叶子大,挂右边 return OK 3二叉排序树的删除操作如何实现? 如何删除一个结点? 假设:一p表示被删结点的指针;PL和PR分别表示*P的左、右孩子指针; 若在 A 的屮子甘的 挖亍时 上 J*入姑 A,血乂的*斷因子从-塔扣至签 5E 事却疔顾 Mfi驴齐建时 针如/、j 鼻 人的 佶 ju内撬转匸二 学习重点: 查找表是称为集合的数据结构。 因元素间关系非常松散, 其操作需借助其它数据结构来 实现。 本章
47、列举了三种方法(静 态查找表,动态查找表)实现查找表的运算。 顺序表因设置了监视哨使查找效率大大提高。有序表的平均查找长度不超过树的深度。 查找的ASL *f表示*p的双亲结点指针;并假定*p是*f的左孩子;则可能有三种情况: |巾为叶了 LJW 除此结点时”直接悔改曲域即可: 彳打只有 Tt 了讨(虹或右)锂卑吃为*f 曲左曲子即町: I 衍有两操子樹=悟况矍琳-4 二叉排序树的形态取决于元素的输入顺序。按中序遍历可得到结点的有序序列,应熟练 掌握其建立、查找,插入和 删除算法。 平衡二叉树的概念,应熟练掌握手工绘制平衡二叉树。 二叉排序树的 AS.2(l + -L)ln it 1 平衡二叉
48、树的定义: 又称AVL树,即它或者是一颗空树, 或者是它的左子树和右子树都 是平衡二叉树,且左子树与右子树的深度之差的绝对值不超过1。 平衡因子:该结点的左子树的深度减去它的右子树的深度。 平衡二叉树的特点:任一结点的平衡因子只能取:-1、0或1。 如果在一棵AVL树中插入一个新结点,就有可能造成失衡,此时必须重新调整树的结构, 使之恢复平衡。我们称调 整平衡过程为平衡旋转。 3) LR平衡康转: 若 灰 A 的士子甘的 右子+上 J6 人 A, TltA 的辛街因子从 L 堆加生1,需奂 st 琨好够叶汁程转.再 4) RL平衡族转: 补充: 1.查找的过程是怎样的? 给定一个值K,在含有n
49、个记录的文件中进行搜索,寻找一个关键字值等于K的记录, 如找到则输出该记录,否则输出查找不成功的信息。 2.对查找表常用的操作有哪些? 查询某个“特定的”数据元素是否在表中; 查询某个“特定的”数据元素的各种属性; 在查找表中插入一元素; 从查找表中删除一元素。 3.哪些查找方法? 查找方法取决于表中数据的排列方式; 4.如何评估查找方法的优劣? 用比较次数的平均值来评估算法的优劣。称为平均查找长度ASL。 ASL=刀Pi. Ci 5.使用折半查找算法时,要求被查文件:采用顺序存贮结构、记录按关键字递增有序 6.将线性表构造成二叉排序树的优点: 1查找过程与顺序结构有序表中的折半查找相似,查找
50、效率高; 2中序遍历此二叉树,将会得到一个关键字的有序序列(即实现了排序运算); 平衡旋转可以归纳为四类: 1 LL平衡旋转: 轴魂” niAftS牛布囚子派1堆加垂 2, 齢筑忙-心 5 时针盖稱* 野在也站占干禅阳 生 子樽上妞 人 箱点+ OtA 昨平衙凶子啟 1 期抽 3如果查找不成功,能够方便地将被查元素插入到二叉树的叶子结点上,而且插入或删除 时只需修改指针而不需移 动元素。 第九章 内部排序 内容提要: 排序的定义,排序可以看作是线性表的一种操作 排序:将一组杂乱无章的数据按一定的规律顺次排列起来。 排序的分类,稳定排序与不稳定排序的定义。 稳定性一一若两个记录A和B的关键字值相