存储管理查找和排序.docx
《存储管理查找和排序.docx》由会员分享,可在线阅读,更多相关《存储管理查找和排序.docx(8页珍藏版)》请在冰豆网上搜索。
![存储管理查找和排序.docx](https://file1.bdocx.com/fileroot1/2023-2/3/70a02a76-9a53-457d-91d1-caafeec6132b/70a02a76-9a53-457d-91d1-caafeec6132b1.gif)
存储管理查找和排序
存储管理、查找和排序
题目:
内部排序算法比较
问题描述:
通过随机数据比较各算法的关键字比较次数与移动次数
基本要求:
至少比较快速排序与堆排序。
对结果进行简单分析
一、需求分析
1.排序算法的基本操作
大多数排序算法都有两个基本的操作:
(1)比较两个关键字的大小;
(2)改变指向记录的指针或移动记录本身。
注意:
第
(2)种基本操作的实现依赖于待排序记录的存储方式。
2.待排文件的常用存储方式
(1)以顺序表(或直接用向量)作为存储结构
排序过程:
对记录本身进行物理重排(即通过关键字之间的比较判定,将记录移到合适的位置)
(2)以链表作为存储结构
排序过程:
无须移动记录,仅需修改指针。
通常将这类排序称为链表(或链式)排序;
(3)用顺序的方式存储待排序的记录,但同时建立一个辅助表(如包括关键字和指向记录位置的指针组成的索引表)
排序过程:
只需对辅助表的表目进行物理重排(即只移动辅助表的表目,而不移动记录本身)。
适用于难于在链表上实现,仍需避免排序过程中移动记录的排序方法。
3.排序算法性能评价
(1)评价排序算法好坏的标准
评价排序算法好坏的标准主要有两条:
1执行时间和所需的辅助空间
2算法本身的复杂程度
(2)排序算法的空间复杂度
若排序算法所需的辅助空间并不依赖于问题的规模n,即辅助空间是O
(1),则称之为就地排序(In-PlaceSou)。
非就地排序一般要求的辅助空间为O(n)。
(3)排序算法的时间开销
大多数排序算法的时间开销主要是关键字之间的比较和记录的移动。
有的排序算法其执行时间不仅依赖于问题的规模,还取决于输入实例中数据的状态。
快速排序:
快速排序有两个方向,左边的i下标一直往右走,当a[i]<=a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。
而右边的j下标一直往左走,当a[j]>a[center_index]。
如果i和j都走不动了,i<=j,交换a[i]和a[j],重复上面的过程,直到i>j。
交换a[j]和a[center_index],完成一趟快速排序。
在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为53343891011,现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。
堆排序:
我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。
在一个长为n的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。
但当为n/2-1,n/2-2,...1这些个父节点选择元素时,就会破坏稳定性。
有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。
所以,堆排序不是稳定的排序算法。
二、概要设计
模块:
1.结构体
2.快速排序算法
3.堆排序算法
三、详细设计
1.结构体:
typedefstruct
{
intlength;
intnum[101];
}NUM;
2.快速排序
voidquick_sort(NUM&a,intl,inth,int&move_count,int&judge_count)
{
intlow=l;
inthigh=h;
intm;
if(low{
m=one_quick_sort(a,low,high,move_count,judge_count);
quick_sort(a,1,m-1,move_count,judge_count);
quick_sort(a,m+1,high,move_count,judge_count);
}
}
3.堆排序
voidheap_sort(NUM&a,int&move_count,int&judge_count)
{
for(inti=a.length/2;i>0;--i)
{
heap_adjust(a,i,a.length,move_count,judge_count);
}
for(inti=a.length;i>1;--i)
{
swap(a.num[1],a.num[i]);
move_count+=3;
heap_adjust(a,1,i-1,move_count,judge_count);
}
}
四、调试分析
1.对正序、逆序和若干不同程度随机打乱的可排序表,进行各种排序方法的比较测试,得到的测试数据具有较好的典型性和可比较性。
通过设计和实现指定程度的随机乱序算法,对伪随机数序列的产生有了具体的认识和实践。
2.本实习作业采用循序渐进的策略。
首先设计和实现可排序表的建立和打乱操作,然后用插入排序验证各种内部辅助操作的正确性,进而逐个加入其他排序算法,最后完成对测试结果比较表的显示。
调试能力有了提高。
五、用户手册
统计在快速排序、堆排序、直接插入排序中,数字的移动次数和判断次数。
并且输出排序后的序列.
输入数字的长度和数字然后回车
六、测试结果
测试
快速排序
堆排序
比较
次数
少
乱否差异小
稍多
乱否差异很小
移动
次数
第二少
乱否差异较小
稍多
乱否差异很小
七、源程序清单
#include"stdafx.h"#includeusingnamespacestd;typedefstruct{intlength;intnum[101];}NUM;intone_quick_sort(NUM&a,intL,intH,int&move_count,int&judege_count){intprivotkey=a.num[L];intlow=L;inthigh=H;a.num[0]=privotkey;++move_count;while(low=a.num[low]){++low;++judege_count;}a.num[high]=a.num[low];++move_count;}a.num[low]=privotkey;++move_count;returnlow;}voidquick_sort(NUM&a,intl,inth,int&move_count,int&judge_count){intlow=l;inthigh=h;intm;if(lowjudge(a.num[j],a.num[j+1],judge_count)){j++;}if(judge(rc,a.num[j],judge_count)){break;}a.num[s]=a.num[j];++move_count;s=j;}a.num[s]=rc;++move_count;}voidswap(int&a,int&b){ints;s=a;a=b;b=s;}voidheap_sort(NUM&a,int&move_count,int&judge_count){for(inti=a.length/2;i>0;--i){heap_adjust(a,i,a.length,move_count,judge_count);}for(inti=a.length;i>1;--i){swap(a.num[1],a.num[i]);move_count+=3;heap_adjust(a,1,i-1,move_count,judge_count);}}int_tmain(intargc,_TCHAR*argv[]){NUMa,b,c;cout<<"pleaseinputlengthofthenumber:
"<>a.length;b.length=a.length;c.length=b.length;cout<<"pleaseinputthenumber:
"<>a.num[i];b.num[i]=a.num[i];c.num[i]=a.num[i];}intmove_count=0;intjudge_count=0;//快速排序cout<<"quicksort:
"<"<"<"<";heap_sort(c,move_count,judge_count);cout<<"move_count:
"<"<"<=1;--i){cout<