数据结构第九章
《数据结构》_第9章 图

int edges[MAXV][MAXV]; int vexnum,arcnum; VertexType vexs[MAXV];
} MGraph;
9.2.2
邻接表存储方法
图的邻接表存储方法是一种顺序分配与链式分配相结 合的存储方法。在邻接表中,对图中每个顶点建立一个单链 表,第i个单链表中的结点表示依附于顶点vi 的边(对有向图 是以顶点vi为尾的弧)。每个单链表上附设一个表头结点。 表结点和表头结点的结构如下: 表结点 advex nextarc info 表头结点
(2)在邻接表上查找相邻结点,找到后修改相应邻接矩阵元素 的值。算法如下: void ListToMat(ALGraph *G,MGraph &g) /*将邻接表G转换成邻接矩阵g*/ { int i,j,n=G->n;ArcNode *p; for (i=0;i<n;i++) /*g.edges[i][j]赋初值0*/ for (j=0;j<n;j++) g.edges[i][j]=0; for (i=0;i<n;i++) { p=G->adjlist[i].firstarc; while (p!=NULL) { g.edges[i][p->adjvex]=1; p=p->nextarc; } } g.vexnum=n;g.arcnum=G->e; }
(5)对于有向图,邻接矩阵的第i行(或第i列)非零元素(或 非∞元素)的个数正好是第i个顶点vi的出度(或入度)。 (6)用邻接矩阵方法存储图,很容易确定图中任意两个顶 点之间是否有边相连。但是,要确定图中有多少条边,则必须 按行、按列对每个元素进行检测,所花费的时间代价很大。 这是用邻接矩阵存储图的局限性。
数据结构教程 第九章 排序

9.2.3 希尔排序
3.算法
void ShellSort() { gap=n/2;//初次增量取序列元素个数n的一半为步长 while(gap>0) { for(i=gap+1;i<=n;i++) { j=i-gap; while(j>0) { if(r[j]>r[j+gap]) { x=r[j];r[j]=r[j+gap];r[j+gap]=x; j=j-gap; }//对子序列作直接插入排序 else j=0; } } gap=gap/2;}//每次减半,直至步长为1 上一页 }
上一页
下一页
9.3 快速排序法
9.3.2 快速排序
3【例9-5】对数据序列:70, 75, 69, 32, 88, 18, 16, 58进行快速排序如图9-3所示。 4.算法
void QuickSort(int low, int high)//递归形式的快速排序 { int pivotpos; if(low<high) { pivotpos=Partition(low,high); QuickSort(low,pivotpos-1);//对低子表递归排序 QucikSort(pivotpos+1,high);//对高子表递归排序 } }
9.2 插入排序
9.2.2 二分插入排序
3.算法
void BinsSort() { for(i=2;i<=n;i++) { r[0]=r[i];low=1;high=i-1;//将r[i]暂存到r[0] while(low<=high) //在r[low..high]中折半查找有序插入的位置 { m=(low+high)/2;//折半 if(r[0].key<r[m].key) high=m-1;//插入点在低半区 else low=m+1;//插入点在高半区 } for(j=i-1;j>high+1;--j) r[j+1]=r[j];//记录后移 r[high+1]r[0];//插入 } 上一页 下一页
数据结构第9章 排序

R[3] 10
R[4] 60
R[5] 25
R[6] 30
R[7] 18 18 18 18
18 36 20
10 10 36
60 60 60
25 25 25
30 30 30
【算法】直接插入排序 void D_InsertSort(datatype R[ ], int n) { /*对排序表R[1]..R[n]进行直接插入排序,n是记录的 个数*/ for(i=2; i<=n; i++) if (R[i].key<R[i-1].key) {R[0]=R[i]; /*将R[i]插入R[1].. R[i-1]中, R[0]为监测哨*/ for(j=i-1; R[0].key<R[j].key; j--) R[j+1]=R[j]; /*后移记录*/ R[j+1]=R[0]; /*插入到合适位置*/ } }
空间性能:除排序表以外的内存占用情况。 时间性能:比较关键码的次数,数据移动的次数。 它们往往是排序表规模(n)的函数
6. 记录和排序表的数据结构
一般采用顺序结构存储排序表。 记录和排序表的类型定义如下: #define MAXNUM … /* MAXNUM 为足够大的数 typedef struct { keytype key; …… } datatype; datatype R[MAXNUM]; /*关键码字段*/ /*其它信息*/ /*记录类型*/ /*定义排序表的存储
第一趟排序结果,使得间隔为5的字表有序: P=3
29 7 41 30 11 39 50 76 41 13 10 0 80 78 86
子序列分别为:{29,30,50,13,78},{7,11,76,100,86}, {41,39,41,80}。第二趟排序结果: P=1
数据结构第9章 排序

数据结构第9章排序数据结构第9章排序第9章排名本章主要内容:1、插入类排序算法2、交换类排序算法3、选择类排序算法4、归并类排序算法5、基数类排序算法本章重点难点1、希尔排序2、快速排序3、堆排序4.合并排序9.1基本概念1.关键字可以标识数据元素的数据项。
如果一个数据项可以唯一地标识一个数据元素,那么它被称为主关键字;否则,它被称为次要关键字。
2.排序是把一组无序地数据元素按照关键字值递增(或递减)地重新排列。
如果排序依据的是主关键字,排序的结果将是唯一的。
3.排序算法的稳定性如果要排序的记录序列中多个数据元素的关键字值相同,且排序后这些数据元素的相对顺序保持不变,则称排序算法稳定,否则称为不稳定。
4.内部排序与外部排序根据在排序过程中待排序的所有数据元素是否全部被放置在内存中,可将排序方法分为内部排序和外部排序两大类。
内部排序是指在排序的整个过程中,待排序的所有数据元素全部被放置在内存中;外部排序是指由于待排序的数据元素个数太多,不能同时放置在内存,而需要将一部分数据元素放在内存中,另一部分放在外围设备上。
整个排序过程需要在内存和外存之间进行多次数据交换才能得到排序结果。
本章仅讨论常用的内部排序方法。
5.排序的基本方法内部排序主要有5种方法:插入、交换、选择、归并和基数。
6.排序算法的效率评估排序算法的效率主要有两点:第一,在一定数据量的情况下,算法执行所消耗的平均时间。
对于排序操作,时间主要用于关键字之间的比较和数据元素的移动。
因此,我们可以认为一个有效的排序算法应该是尽可能少的比较和数据元素移动;第二个是执行算法所需的辅助存储空间。
辅助存储空间是指在一定数据量的情况下,除了要排序的数据元素所占用的存储空间外,执行算法所需的存储空间。
理想的空间效率是,算法执行期间所需的辅助空间与要排序的数据量无关。
7.待排序记录序列的存储结构待排序记录序列可以用顺序存储结构和和链式存储结构表示。
在本章的讨论中(除基数排序外),我们将待排序的记录序列用顺序存储结构表示,即用一维数组实现。
《 数据结构第九章

4、折半插入排序 折半插入排序算法的描述如下:
1 void BinSort(RecordType r[ ], int length)
2 { /*对记录数组r进行折半插入排序,length为数组的长度*/
3 for(i=2; i<=length; ++i)
4 { x= r[i];
5 low=1; high=i-1;
例如,待排序列为39,80,76,41,13,29,50,78,30,11, 100,7,41,86。增量分别取5、3、1,则排序过程如图9.4所示。
图9.4 希尔排序过程示例
图9.4 希尔排序过程示例
2、算法实现 希尔排序算法如下:
1 void ShellInsert(SqList *L, int delta)
表插入排序算法描述如下:
1 void SLinkListSort(RecordType1 r[], int length)
2 { int n=length;
3 r[0].next=1; r[1].next=0; /*构造只有一个元素的有序静态循环链表*/
4 for(i=2; i<=n-1; i++)
整队(或排列)的操作。
排序的定义:
假设含有n个记录的序列为:{r1,r2,…,rn}
(9-1)
它们的关键字相应为:{k1,k2,…,kn}。
对式(9-1)的记录序列进行排序就是要确定序号1,2,…,n的一种排列:
{p1,p2,…,pn}
使其相应的关键字满足如下的非递减(或非递增)的关系:
kp1≤kp2≤…≤kpn
/*将待插入记录复制为哨兵*/
7 j=i-1;
8 while(L->r[0].key<L->r[j].key)
数据结构--第九章

/*对记录数组r做简单选择排序,length为数组的长度*/
{ n=length;
for ( i=1 ; i<= n-1; ++i)
{k=i;
for ( j=i+1 ; j<= n ; ++j)
if (r[j].key < r[k].key ) k=j;
if ( k!=i)
{ x= r[i]; r[i]= r[k]; r[k]=x; } }
9.4.1 简单选择排序
基本思想:第i趟简单选择排序是指通过n-i次关键字 的比较,从n-i+1个记录中选出关键字最小的记录, 并和第i个记录进行交换。共需进行i-1趟比较,直到 所有记录排序完成为止。
选择排序示例见P240的图9.5所示。
返回主目录
.
简单选择排序的算法描述如下:
void SelectSort(RecordType r[], int length)
返回主目录
.
例 13
38
27
50 76 65 49
97
97
38
27
50 76 65 49
13 输出:13
27
38
49
50 76 65 97
13 输出:13
返回主目录
.
9.2 插入类排序
基本思想:在一个已排好序的记录子集的基础上,每一步将 下一个待排序的记录有序插入到已排好序的记录子集中,直
到将所有待排记录全部插入为止。
9.2.1 直接插入排序
基本操作是将第i个记录插入到前面i-1个已排好序的记录中, 具体过程为:将第i个记录的关键字Ki顺次与其前面记录的 关键字Ki-1,Ki-2,…K1进行比较,将所有关键字大于Ki的 记录依次向后移动一个位置,直到遇见一个关键字小于或者 等于Ki的记录Kj,此时Kj后面必为空位置,将第i个记录插 入空位置即可。
数据结构 第九章

排序过程演示:
课程代码:0600060
计算机科学与工程系
25
2)算法分析
时间复杂度:
记录移动次数
最好情况:0 最坏情况:3(n-1)
比较次数:直接选择排序的关键字比较次数与对 象的初始排列无关。
第 i 趟选择具有最小关键字对象所需的比较次数总是 n-i次; n 1 1 ( n i ) ( n 2 n) 因此,总的关键字比较次数为: 2
课程代码:0600060
计算机科学与工程系
16
2)算法实现
void bubbleSort (SeqList R, int length) //起泡排序算法 { int i, j, exchange=1; /* exchange为发生交换标志*/ for ( i = length; i>=1 &&exchange; i--) {exchange =0; for (j=1;j<i; j++) if (R[j].key > R[j+1].key) { R[0]=R[j]; /* 发生逆序,用R[0]做暂存单元 */ R[j]=R[j+1]; R[j+1]=R[0]; exchange=1; /* 做“发生了交换”标志 */ }
课程代码:0600060 计算机科学与工程系 22
9.4 选择排序
基本思想:
每一趟排序 (如第 i 趟,i = 1, 2, …, n-1) 在
n-i+1 个待排序对象中选出关键字最小的对 象, 作为有序序列的第 i 个对象。 待第 n-1 趟排序后,待排序对象只剩下1个, 就不用再选了。
《数据结构》第九章习题 参考答案

《数据结构》第九章习题参考答案一、判断题(在正确说法的题后括号中打“√”,错误说法的题后括号中打“×”)1、快速排序是一种稳定的排序方法。
(×)2、在任何情况下,归并排序都比简单插入排序快。
(×)3、当待排序的元素很大时,为了交换元素的位置,移动元素要占用较多的时间,这是影响时间复杂度的主要因素。
(√)4、内排序要求数据一定要以顺序方式存储。
(×)5、直接选择排序算法在最好情况下的时间复杂度为O(n)。
( ×)6、快速排序总比简单排序快。
( ×)二、单项选择题1.在已知待排序文件已基本有序的前提下,效率最高的排序方法是(A)。
A.直接插入排序B.直接选择排序C.快速排序D.归并排序2.下列排序方法中,哪一个是稳定的排序方法?(B)A.直接选择排序B.折半插入排序C.希尔排序D.快速排序3、比较次数与排序的初始状态无关的排序方法是( B)。
A.直接插入排序B.起泡排序(时间复杂度O(n2))C.快速排序D.简单选择排序4、对一组数据(84,47,25,15,21)排序,数据的排列次序在排序的过程中的变化为(1)84 47 25 15 21 (2)15 47 25 84 21 (3)15 21 25 84 47 (4)15 21 25 47 84 则采用的排序是( A)。
A. 选择B. 冒泡C. 快速D. 插入5、快速排序方法在(D)情况下最不利于发挥其长处。
A. 要排序的数据量太大B. 要排序的数据中含有多个相同值C. 要排序的数据个数为奇数D. 要排序的数据已基本有序6、用某种排序方法对线性表{25,84,21,47,15,27,68,35,20}进行排序,各趟排序结束时的结果为:(基准)20,21,15,25,84,27,68,35,47(25)15,20,21,25,47,27,68,35,84(左20右47)15,20,21,25,35,27,47,68,84(左35右68)15,20,21,25,27,35,47,68,84 ;则采用的排序方法为(C)。
数据结构 第9章 查找3-B树

插入关键字 = 60, 90, 30
2、B-树的删除
在深度为(h+l)的m阶B-树中删除一个键值k,首先要查 到键值k所在的结点及在结点中的位置。若k在非终端 节点中,则把该结点的右边(或左边)指针所指子树中 的最小(或最大)键值与k对调,使k移到终端节点。 在终端节点中删除一个键值后,使得该结点的值个数n 减1,此时应分以下三种情况进行处理: – (1)若删除后结点中键值数目n≥ ┌m/2┐-1,在该结点 中删去键值k连同右边的指针。 – (2)若删除后结点中键值数目n< ┌m/2┐ -1,且左(或 右)兄弟结点的关键字数目> ┌m/2┐-1,则把左(或 右)兄弟结点中最大(或最小)键值移到父结点中,再 把父结点大于(或小于)上移键值的键值下移到被删 关键字所在结点中。
(3)若删除后结点中键值数目n< ┌m/2┐ -1,及 其左、右兄弟结点的键值数目都等于┌m/2┐ -1,则就必须进行结点的“合并”,即把应删 的键值删去后,将该结点中的剩余键值和指针 连同父结点中指向该结点指针的左边(或右边) 一个键值ki一起合并到左兄弟(或右兄弟)结点 中,将ki从父结点中删去。如果因此使父结点 中关键字数目< ┌m/2┐-1,则对此父结点做同 样处理,以致于可能直到对根结点做这样的处 理而使整个树减少一层。
2.查找性能的分析
在B-树中进行查找时,其查找时间 主要花费在搜索结点(访问外存)上, 即主要取决于B-树的深度 树的深度。 树的深度
问:含 N 个关键字的 m 阶 B-树可 能达到的最大深度 H 为多少?
反过来问: 深度为H的B-树中, 至少含有多少个结点? 先推导每一层所含最少结点数: 第1层 第2层 第3层 第4层 … … 第 H+1 层 1个 2个 2×m/2 个 × 2×(m/2)2 个 × 2×(m/2) H-1 个 ×
数据结构第九章动态查找

当数据结构中元素数量较大,且元素顺序不重要时,可以使
哈希查找是一种基于哈希表的查找算法,通过将键映
射到哈希表中对应的槽位,快速定位到元素。
02
哈希查找的时间复杂度为O(1),即平均时间复杂度为
常数时间,具有很高的查找效率。
03
哈希查找适用于数据量较大且数据插入、删除频繁的
平衡二叉树
如AVL树和红黑树,保持树平衡以实现高效的查找、插入和删除操作。
B树和B+树
适用于磁盘或其它直接存储设备上的数据查找,能够减少磁盘I/O操作。
算法的优化与改进
01
哈希表的负载因子
合理设置哈希表的负载因子,以 平衡哈希表的查找性能和冲突率。
02
平衡二叉树的旋转 操作
在插入和删除节点时,通过旋转 操作保持树的平衡,提高查找效 率。
03
B树和B+树的分裂 与合并
在节点分裂和合并时,合理调整 节点数据,减少磁盘I/O操作。
实际应用案例分析
数据库索引
数据库索引使用哈希表、B树或B+树等数据结构,以 提高数据查找速度。
搜索引擎
搜索引擎使用倒排索引、B树或B+树等数据结构,快 速定位网页内容。
文件系统
许多现代文件系统使用B树或B+树等数据结构,以提 高文件查找、读取和写入速度。
THANKS
感谢观看
额外空间复杂度
对于某些动态查找算法,如二分查找,需要额外的空间来存储中间结果,因此 其空间复杂度为O(log n)。而哈希表查找等其他算法则不需要额外的空间,其 空间复杂度为O(1)。
05
动态查找的实践应用
数据结构的选择
哈希表
适用于快速查找,但需要处理哈希冲突。
数据结构第九章

1 查找失败: · n=n i 1 n
假设被查找的记录在顺序表中的概率为p,不在顺序表中的概率为q,则
n
考虑了查找成功或失败两种情况下的平均查找长度为:
ASLsq=p(n+1)/2 +q(n+l)=(n+1)(1- p/2)
顺序查找小结
简单,查找效率却较低。 当已知各记录的查找频率不等时,可以改 变记录的存储次序:
顺序存储结构 顺序存储结构 线性链表
当顺序表中记录的个数非常大,建立了多级索引表的建立
可以有效地提高查找速度。
付出的代价是增加辅助存储空间和将顺序表分块排序; 好
处是不需要对全部记录进行排序。
9.3动态查找技术
内部结点
1
3 5 2 2~3 3~4 4 4~5 5~6 6 6~7 8 9
11 13 10 8~9 7~8 12 10~11 9~10
27:⑦—③—⑤—④
外部结点
130:7—11—13—12 —12~13
14 12~13 14~15
0 0~1
-1~0
1~2
11~12
13~14
图 9.2.2 描述二分查找过程的二叉判定树
1. 内部结点中的值为对应记录的序号; 2. 外部结点中的两个值表示查找不成功时给定值在记录中所 对应的记录序号范围。
二分查找法的查找效率
假设有序表中记录的个数恰好为:n=20+21+…+2k-1=2k-l则相 应的二叉判定树为深度k=log2(n+1)的满二叉树。在树的第i层 上总共有2i-1个记录结点,查找该层上的每个结点需要进行i次 比较。因此,当表中每个记录的查找概率相等时,查找成功的
把查找频率高的记录尽可能放到序列的前面, 把查找频率低的记录放到序列的后面。
数据结构-第9章 查找

静态查找表 对查找表的查找仅是以查询为 目的,不改动查找表中的数据。 动态查找表 在查找的过程中同时插入不存 在的记录,或删除某个已存在的记录。
查找成功 查找表中存在满足查找条件的记 录。 查找不成功 查找表中不存在满足查找条件 的记录。
内查找 整个查找过程都在内存中进行。 外查找 在查找过程中需要访问外存。 平均查找长度ASL——查找方法时效的度量 为确定记录在查找表中的位置,需和给定值 进行比较的关键字个数的期望值。 n 查找成功时的ASL计算方法: ASL pici
3. 在二叉排序树上的操作
1)查找
[例] Key=28 f 24 12 T
45
53 28 90
Key=32 T 45 24 53 12 f 28 90 32
[算法描述]
2) 插入
[算法描述]
3) 生成
查找算法
返回
BiTree SearchBST(BiTree T,KeyType key){
//在根指针T所指二叉树中递归地查找某关键字等于 //key的数据元素,若查找成功,则返回指向该数据元 //素结点的指针,否则返回空指针
图9.1 用折半查找法查找12、50的过程 其中mid=(low+high)/2,当high<low时,表 示不存在这样的子表空间,查找失败。
成功! 位 置 1 2 3 4 5 6 7 8 9 10 11
值
6 12 15 18 22 25 28 35 45 58 60
low hign mid mid hign mid low mid (a) 用折半查找法查找12的过程
[性能分析] • 空间:一个辅助空间。 • 时间: 查找成功时的平均查找长度 设表中各记录查找概率相等 n ASLs(n)= PiCi =(1+2+ ... +n)/n =(n+1)/2 i 1 [算法特点] • 算法简单,对表结构无任何要求 • n很大时查找效率较低 • 改进措施:非等概率查找时,可将查找概率高 的记录尽量排在表后部。
数据结构 第九章 查找

S P Q
PL
S Q
PL 中序遍历:PL P S Q
(1)
6
中序遍历:PL S Q
3 2 4 15
18
S Q P
S Q PL
PL 中序遍历:Q S PL P
1)分块有序(升序或降序) ——第I块中的最大(小)值小(大)于第i+1块中的最(大)小值
2)查找 (1)先查索引表——折半查找 (2)再查顺序表——顺序查找 块间有序,块内无序
typedef struct { int key;} Eletype; typedef struct { Elemtype *elem; int length; } SSTable; # define BLOCK_NUM 3
DeleteDSTable(&DT,key);
TraverseDSTable(DT,visit()); //遍历查找表
9.2.1二叉排序树 ( Binary Sort Tree )
定义 二叉排序树(二叉查找树) 或者是一棵空树, 或者是具有下列性质的二叉树: 每个结点都有一个作为查找依据的关键字 (key),所有结点的关键字互不相同。 左子树(若非空)上所有结点的关键字都小于 根结点的关键字。 右子树(若非空)上所有结点的关键字都大于 根结点的关键字。 左子树和右子树也是二叉排序树。
关键字:数据元素中某个数据项的值,用以 标识一个数据元素。 主关键字:可唯一地标识一个数据元素的关 键字。 次关键字:用以识别若干记录的关键字。 使用基于主关键字的查找,查找结果应是 唯一的。
静态查找表(p214) 动态查找表
关键字惟一确定一条记录
属性名 (字段名)
《数据结构》课件ds-09

第九章 排序
1
第九章 排序
概述 插入排序 交换排序 选择排序 归并排序 基数排序
140-2
概述
排序:将一组杂乱无章的数据按一定的规律 顺次排列起来。 数据表(datalist): 它是待排序数据元素的有限 集合。
排序码(key): 通常数据元素有多个属性域, 即 多个数据成员组成, 其中有一个属性域可用来 区分元素, 作为排序依据。该域即为排序码。 每个数据表用哪个属性域作为排序码,要视 具体的应用需要而定。
起泡排序的算法
template <class T> void BubbleSort (dataList<T>& L, const int left, const int right) { int pass = left+1, exchange = 1; while (pass <= right && exchange) { exchange = 0; //标志为0假定未交换 for (int j = right; j >= pass; j--)
140-6
bool operator == (Element<T>& x) { return key == x.key; } //判*this与x相等 bool operator <= (Element<T>& x) { return key <= x.key; } //判*this小于或等于x bool operator >= (Element<T>& x) { return key >= x.key; } //判*this大于或等于x bool operator > (Element<T>& x) { return key > x.key; } //判*this大于x bool operator < (Element<T>& x) { return key < x.key; } //判*this小于x
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
甘肃政法学院
本科生实验报告
(2)
姓名:田学成
学院:公安技术学院
专业:信息安全
班级:13信息安全班
实验课程名称:实验日期:2014年5月21日
指导教师及职称:金涛
实验成绩:
开课时间: 2013-2014 学年第二学期
甘肃政法学院实验管理中心印制
第九章
文件包含函数BinSearch的功能是采用二分查找方法在顺序表R中查找关键字K的记录位置
1.
2..
文件包含的函数InxSearch(ID I,int m,SequList R,int n,Key,Type k)的功能采用分块查找方法在顺苏北R中查找关键字的K的位置
CreatBst由数组A中的关键字创建一颗二叉序列树
CreaTree采用递归方式构造一个二叉排序树InOrder中遍历输出BST
LeftProgress在插入节点时对以指针P所指节点为二叉树做左平衡旋转处理相反RightProgress则做右平衡旋转,
根据题目要求编写程序调试执行
InsertSort功能是对R按递增有序进行直接的插入排序
第十章
3..
.
4.
.。