数据结构C语言版第九章 内部排序.docx
- 文档编号:10959909
- 上传时间:2023-02-24
- 格式:DOCX
- 页数:17
- 大小:156.29KB
数据结构C语言版第九章 内部排序.docx
《数据结构C语言版第九章 内部排序.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版第九章 内部排序.docx(17页珍藏版)》请在冰豆网上搜索。
数据结构C语言版第九章内部排序
第九章内部排序
重点难点
要求掌握与排序相关的基本概念,如关键字的比较次数、数据移动次数、稳定性、内部排序。
深刻理解各种排序的基本思想和各种排序方法的特点、实现方法,并能加以灵活应用;掌握各种排序方法的时间复杂度的分析方法。
典型例题
1.若文件初态是反序的,且要求输入稳定,则在直接插入、直接选择、冒泡和快速排序中就选选哪种方法为宜?
答:
这四种排序算法中,直接选择、快速排序均是不稳定的,因此先予以排除,剩下两种算法中,由于直接插入算法所费时间比冒泡法更少,因此选择直接排序算法为宜。
2.判别下列序列是否为堆(小根堆或大根堆),若不是,则将其调整为堆:
(1)(100,86,73,35,39,42,57,66,21);
(2)(12,70,33,65,24,56,48,92,86,33);
(3)(103,97,56,38,66,23,42,12,30,52,06,20);
(4)(05,56,20,23,40,38,29,61,35,76,28,100).
答:
堆的性质是:
任一非叶结点上的关键字均不大于(或不小于)其孩子结点上的关键字。
据此我们可以通过画二叉树来进行判断和调整:
(1)此序列是大根堆。
(2)此序列不是堆,经调整后成为小根堆:
(12,24,33,65,33,56,48,92,86,70)
(3)此序列是一大根堆。
(4)此序列不是堆,经调整后成为小根堆:
(01,05,20,23,28,38,29,56,35,76,40,100)
3.若关键字是非负整数、快速排序、归并、堆和基数排序啊一个最快?
若要求辅助空间为O
(1),则应选择谁?
若要求排序是稳定的,且关键字是实数,则应选择谁?
答:
若关键字是非负整数,则基数排序最快;若要求辅助空间为O
(1),则应选堆排序;若要求排序是稳定的,且关键字是实数,则应选归并排序,因为基数排序不适用于实数,虽然它也是稳定的。
4.在以下的排序方法中,哪些易于在链表(包括各种单、双、循环链表)上实现?
(1)直接插入排序
(2)希尔排序(3)冒泡排序(4)快速排序
(5)直接选择排序(6)堆排序(7)归并排序(8)基数排序
答:
上题的排序方法中,直接插入排序、冒泡排序、直接选择排序、基数排序和归并排序等方法易于在链表上实现。
5.以单链表作为存储结构实现直接插入排序算法。
解:
#defineintKeyType//定义KeyType为int型
typedefstructnode{
KeyTypekey;//关键字域
OtherInfoTypeinfo;//其它信息域,
structnode*next;//链表中指针域
}RecNode;//记录结点类型
typedefRecNode*LinkList;//单链表用LinkList表示
voidInsertSort(LinkListhead)
{//链式存储结构的直接插入排序算法,head是带头结点的单链表
RecNode*p,*q,*s;
if((head->next)&&(head->next->next))//当表中含有结点数大于1
{
p=head->next->next;//p指向第二个节点
head->next=NULL;
q=head;//指向插入位置的前驱节点
while(p)&&(q->next)&&(p->key
q=q->next;
if(p)
{s=p;p=p->next;//将要插入结点摘下
s->next=q->next;//插入合适位置:
q结点后
q->next=s;
}
}
}
6.将哨兵放在R[n]中,被排序的记录放在R[0..n-1]中,重写直接插入排序算法。
解:
重写的算法如下:
voidInsertSort(SeqListR)
{//对顺序表中记录R[0..n-1]按递增序进行插入排序
inti,j;
for(i=n-2;i>=0;i--)//在有序区中依次插入R[n-2]..R[0]
if(R[i].key>R[i+1].key)//若不是这样则R[i]原位不动
{
R[n]=R[i];j=i+1;//R[n]是哨兵
do{//从左向右在有序区中查找插入位置
R[j-1]=R[j];//将关键字小于R[i].key的记录向右移
j++;
}while(R[j].key R[j-1]=R[n];//将R[i]插入到正确位置上 }//endif }//InsertSort. 习题精选 1.选择题 (1)从未排序序列中依次取出元素与已排序序列中的元素进行比较,将其放入已排序序列的正确位置上的方法,这种排序方法称为()。 A.归并排序B.冒泡排序C.插入排序D.选择排序 (2)从未排序序列中挑选元素,并将其依次放入已排序序列(初始时为空)的一端的方法,称为()。 A.归并排序B.冒泡排序C.插入排序D.选择排序 (3)对n个不同的关键字由小到大进行冒泡排序,在下列()情况下比较的次数最多。 A.从小到大排列好的B.从大到小排列好的 C.元素无序D.元素基本有序 (4)对n个不同的排序码进行冒泡排序,在元素无序的情况下比较的次数最多为()。 A.n+1B.nC.n-1D.n(n-1)/2 (5)快速排序在下列()情况下最易发挥其长处。 A.被排序的数据中含有多个相同排序码 B.被排序的数据已基本有序 C.被排序的数据完全无序 D.被排序的数据中的最大值和最小值相差悬殊 (6)对n个关键字作快速排序,在最坏情况下,算法的时间复杂度是()。 A.O(n)B.O(n2)C.O(nlog2n)D.O(n3) (7)若一组记录的排序码为(46,79,56,38,40,84),则利用快速排序的方法,以第一个记录为基准得到的一次划分结果为()。 A.38,40,46,56,79,84B.40,38,46,79,56,84 C.40,38,46,56,79,84D.40,38,46,84,56,79 (8)下列关键字序列中,()是堆。 A.16,72,31,23,94,53B.94,23,31,72,16,53 C.16,53,23,94,31,72D.16,23,53,31,94,72 (9)堆是一种()排序。 A.插入B.选择C.交换D.归并 (10)堆的形状是一棵()。 A.二叉排序树B.满二叉树C.完全二叉树D.平衡二叉树 (11)若一组记录的排序码为(46,79,56,38,40,84),则利用堆排序的方法建立的初始堆为()。 A.79,46,56,38,40,84B.84,79,56,38,40,46 C.84,79,56,46,40,38D.84,56,79,40,46,38 (12)下述几种排序方法中,要求内存最大的是()。 A.希尔排序B.快速排序C.归并排序D.堆排序 (13)下述几种排序方法中,()是稳定的排序方法。 A.希尔排序B.快速排序C.归并排序D.堆排序 (14)数据表中有10000个元素,如果仅要求求出其中最大的10个元素,则采用()算法最节省时间。 A.冒泡排序B.快速排序C.简单选择排序D.堆排序 (15)下列排序算法中,()不能保证每趟排序至少能将一个元素放到其最终的位置上。 A.希尔排序B.快速排序C.冒泡排序D.堆排序 2.应用题 (1)设待排序的关键字序列为{12,2,16,30,28,10,16*,20,6,18},试分别写出使用以下排序方法,每趟排序结束后关键字序列的状态。 直接插入排序 ②折半插入排序 希尔排序(增量选取5,3,1) 冒泡排序 快速排序 简单选择排序 堆排序 二路归并排序 直接插入排序 [212]1630281016*20618 [21216]30281016*20618 [2121630]281016*20618 [212162830]1016*20618 [21012162830]16*20618 [210121616*2830]20618 [210121616*202830]618 [2610121616*202830]18 [2610121616*18202830] ②折半插入排序排序过程同 希尔排序(增量选取5,3,1) 102166181216*203028(增量选取5) 621210181616*203028(增量选取3) 2610121616*18202830(增量选取1) 冒泡排序 21216281016*20618[30] 212161016*20618[2830] 212101616*618[202830] 2101216616*[18202830] 21012616[16*18202830] 210612[1616*18202830] 2610[121616*18202830] 2610121616*18202830] 快速排序 12[6210]12[283016*201618] 6[2]6[10]12[283016*201618] 28261012[181616*20]28[30] 18261012[16*16]18[20]2830 16*26101216*[16]18202830 左子序列递归深度为1,右子序列递归深度为3 简单选择排序 2[121630281016*20618] 26[1630281016*201218] 2610[30281616*201218] 261012[281616*203018] 26101216[2816*203018] 2610121616*[28203018] 2610121616*18[203028] 2610121616*1820[2830] 2610121616*182028[30] 二路归并排序 2121630102816*20618 21216301016*2028618 210121616*202830618 2610121616*18202830 堆排序 第一步,形成初始大根堆(详细过程略),第二步做堆排序。 初始排序不是大根堆形成初始大根堆 交换1与10对象从1到9重新形成堆 交换1与9对象从1到8重新形成堆 交换1与8对象从1到7重新形成堆 交换1与7对象从1到6重新形成堆 交换1与6对象从1到5重新形成堆 交换1与5对象从1到4重新形成堆 交换1与4对象从1到3重新形成堆 交换1与3对象从1到2重新形成堆 交换1与2对象得到结果 (2)给出如下关键字序列{321,156,57,46,28,7,331,33,34,63},试按链式基数排序方法,列出每一趟分配和收集的过程。 3.算法设计题 (1)试以单链表为存储结构,实现简单选择排序算法。 voidLinkedListSelectSort(LinkedListhead) //本算法一趟找出一个关键字最小的结点,其数据和当前结点进行交换;若要交换指针,则须记下 //当前结点和最小结点的前驱指针 p=head->next; while(p! =null) {q=p->next;r=p;//设r是指向关键字最小的结点的指针 while(q! =null) {if(q->data q: =q->next; } if(r! =p)r->data<-->p->data; p=p->next; } (2)有n个记录存储在带头结点的双向链表中,现用双向冒泡排序法对其按上升序进行排序,请写出这种排序的算法。 (注: 双向冒泡排序即相邻两趟排序向相反方向冒泡)。 typedefstructnode {ElemTypedata; structnode*prior,*next; }node,*DLinkedList; voidTwoWayBubbleSort(DLinkedListla) //对存储在带头结点的双向链表la中的元素进行双向起泡排序。 {intexchange=1;//设标记 DLinkedListp,temp,tail; head=la//双向链表头,算法过程中是向下起泡的开始结点 tail=null;//双向链表尾,算法过程中是向上起泡的开始结点 while(exchange) {p=head->next;//p是工作指针,指向当前结点 exchange=0;//假定本趟无交换 while(p->next! =tail)//向下(右)起泡,一趟有一最大元素沉底 if(p->data>p->next->data)//交换两结点指针,涉及6条链 {temp=p->next;exchange=1;//有交换 p->next=temp->next;temp->next->prior=p//先将结点从链表上摘下 temp->next=p;p->prior->next=temp;//将temp插到p结点前 temp->prior=p->prior;p->prior=temp; } elsep=p->next;//无交换,指针后移 tail=p;//准备向上起泡 p=tail->prior; while(exchange&&p->prior! =head)//向上(左)起泡,一趟有一最小元素冒出 if(p->data {temp=p->prior;exchange=1;//有交换 p->prior=temp->prior;temp->prior->next=p;//先将temp结点从链表上摘下 temp->prior=p;p->next->prior=temp;//将temp插到p结点后(右) temp->next=p->next;p->next=temp; } elsep=p->prior;//无交换,指针前移 head=p;//准备向下起泡 }//while(exchange) }//算法结束 (3)设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红,白,蓝之一。 要求重新安排这些砾石,使得所有红色砾石在前,所有白色砾石居中,所有蓝色砾石居后,重新安排时对每粒砾石的颜色只能看一次,并且只允许交换操作来调整砾石的位置。 [题目分析]利用快速排序思想解决。 由于要求“对每粒砾石的颜色只能看一次”,设3个指针i,j和k,分别指向红色、白色砾石的后一位置和待处理的当前元素。 从k=n开始,从右向左搜索,若该元素是兰色,则元素不动,指针左移(即k-1);若当前元素是红色砾石,分i>=j(这时尚没有白色砾石)和i 前一情况执行第i个元素和第k个元素交换,之后i+1;后一情况,i所指的元素已处理过(白色),j所指的元素尚未处理,应先将i和j所指元素交换,再将i和k所指元素交换。 对当前元素是白色砾石的情况,也可类似处理。 为方便处理,将三种砾石的颜色用整数1、2和3表示。 voidQkSort(rectyper[],intn) //r为含有n个元素的线性表,元素是具有红、白和兰色的砾石,用顺序存储结构存储, //本算法对其排序,使所有红色砾石在前,白色居中,兰色在最后。 {inti=1,j=1,k=n,temp; while(k! =j) {while(r[k].key==3)k--;//当前元素是兰色砾石,指针左移 if(r[k].key==1)//当前元素是红色砾石 if(i>=j){temp=r[k];r[k]=r[i];r[i]=temp;i++;} //左侧只有红色砾石,交换r[k]和r[i] else{temp=r[j];r[j]=r[i];r[i]=temp;j++; //左侧已有红色和白色砾石,先交换白色砾石到位 temp=r[k];r[k]=r[i];r[i]=temp;i++; //白色砾石(i所指)和待定砾石(j所指) }//再交换r[k]和r[i],使红色砾石入位。 if(r[k].key==2) if(i<=j){temp=r[k];r[k]=r[j];r[j]=temp;j++;} //左侧已有白色砾石,交换r[k]和r[j] else{temp=r[k];r[k]=r[i];r[i]=temp;j=i+1;} //i、j分别指向红、白色砾石的后一位置 }//while if(r[k]==2)j++;/*处理最后一粒砾石 elseif(r[k]==1){temp=r[j];r[j]=r[i];r[i]=temp;i++;j++;} //最后红、白、兰色砾石的个数分别为: i-1;j-i;n-j+1 }//结束QkSor算法 [算法讨论]若将j(上面指向白色)看作工作指针,将r[1..j-1]作为红色,r[j..k-1]为白色,r[k..n]为兰色。 从j=1开始查看,若r[j]为白色,则j=j+1;若r[j]为红色,则交换r[j]与r[i],且j=j+1,i=i+1;若r[j]为兰色,则交换r[j]与r[k];k=k-1。 算法进行到j>k为止。 算法片段如下: inti=1,j=1,k=n; while(j<=k) if(r[j]==1)//当前元素是红色 {temp=r[i];r[i]=r[j];r[j]=temp;i++;j++;} elseif(r[j]==2)j++;//当前元素是白色 else//(r[j]==3当前元素是兰色 {temp=r[j];r[j]=r[k];r[k]=temp;k--;} 对比两种算法,可以看出,正确选择变量(指针)的重要性。 (4)编写算法,对n个关键字取整数值的记录序列进行整理,以使所有关键字为负值的记录排在关键字为非负值的记录之前,要求: 采用顺序存储结构,至多使用一个记录的辅助存储空间; ②算法的时间复杂度为O(n)。 (5)借助于快速排序的算法思想,在一组无序的记录中查找给定关键字值等于key的记录。 设此组记录存放于数组r[l..n]中。 若查找成功,则输出该记录在r数组中的位置及其值,否则显示“notfind”信息。 请简要说明算法思想并编写算法。 [题目分析]把待查记录看作枢轴,先由后向前依次比较,若小于枢轴,则从前向后,直到查找成功返回其位置或失败返回0为止。 intindex(RecTypeR[],intl,h,datatypekey) {inti=l,j=h; while(i {while(i<=j&&R[j].key>key)j--; if(R[j].key==key)returnj; while(i<=j&&R[i].key if(R[i].key==key)returni; } printf(“Notfind”);return0; }//index (6)有一种简单的排序算法,叫做计数排序。 这种排序算法对一个待排序的表进行排序,并将排序结果存放到另一个新的表中。 必须注意的是,表中所有待排序的关键字互不相同,计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键字比该记录的关键字小。 假设针对某一个记录,统计出的计数值为c,那么,这个记录在新的有序表中的合适的存放位置即为c。 给出适用于计数排序的顺序表定义; ②编写实现计数排序的算法; 对于有n个记录的表,关键字比较次数是多少? 与简单选择排序相比较,这种方法是否更好? 为什么? typedefstruct {intkey;datatypeinfo}RecType voidCountSort(RecTypea[],b[],intn)//计数排序算法,将a中记录排序放入b中 {for(i=0;i {for(j=0,cnt=0;j
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构C语言版第九章 内部排序 数据结构 语言版 第九 内部 排序
![提示](https://static.bdocx.com/images/bang_tan.gif)