(完整word版)数据结构各种排序实验报告
- 格式:doc
- 大小:335.50 KB
- 文档页数:29
排序的实验报告范文数据结构实验报告实验名称:实验四排序学生姓名:班级:班内序号:学号:日期:2022年12月21日实验要求题目2使用链表实现下面各种排序算法,并进行比较。
排序算法:1、插入排序2、冒泡排序3、快速排序4、简单选择排序5、其他要求:1、测试数据分成三类:正序、逆序、随机数据。
2、对于这三类数据,比较上述排序算法中关键字的比较次数和移动次数(其中关键字交换计为3次移动)。
3、对于这三类数据,比较上述排序算法中不同算法的执行时间,精确到微秒(选作)。
4、对2和3的结果进行分析,验证上述各种算法的时间复杂度。
编写测试main()函数测试线性表的正确性。
2、程序分析2.1存储结构说明:本程序排序序列的存储由链表来完成。
其存储结构如下图所示。
(1)单链表存储结构:结点地址:1000HA[2]结点地址:1000H1080H……头指针地址:1020HA[0]头指针地址:1020H10C0H……地址:1080HA[3]地址:1080HNULL……地址:10C0HA[1]地址:10C0H1000H……(2)结点结构tructNode{intdata;Node某ne某t;};示意图:intdataNode某ne某tintdataNode某ne某t2.2关键算法分析一:关键算法(一)直接插入排序voidLinkSort::InertSort()直接插入排序是插入排序中最简单的排序方法,其基本思想是:依次将待排序序列中的每一个记录插入到一个已排好的序列中,直到全部记录都排好序。
(1)算法自然语言1.将整个待排序的记录序列划分成有序区和无序区,初始时有序区为待排序记录序列中的第一个记录,无序区包括所有剩余待排序的记录;2.将无须去的第一个记录插入到有序区的合适位置中,从而使无序区减少一个记录,有序区增加一个记录;3.重复执行2,直到无序区中没有记录为止。
(2)源代码voidLinkSort::InertSort()//从第二个元素开始,寻找前面那个比它大的{Node某P=front->ne某t;//要插入的节点的前驱while(P->ne某t){Node某S=front;//用来比较的节点的前驱while(1){if(P->ne某t->data<S->ne某t->data)//P的后继比S的后继小则插入{inert(P,S);break;}S=S->ne某t;if(S==P)//若一趟比较结束,且不需要插入{P=P->ne某t;break;}}}}(3)时间和空间复杂度最好情况下,待排序序列为正序,时间复杂度为O(n)。
数据结构顺序表实验报告全集文档 (可以直接使用,可编辑 实用优质文档,欢迎下载) 洛阳理工学院实验报告 系别 计算机 班级 学号 姓名 课程名称 数据结构 实验日期 10/23 实验名称 顺序表的基本操作 成绩 实验目的: 熟悉掌握线性表顺序存储结构,掌握与应用顺序表的查找、插入、删除等基本操作算法,训练和提高结构化程序设计能力及程序调试能力。 实验条件: 计算机一台,Visual C++6.0 实验内容: 1. 问题描述 以顺序表为存储结构实现以下基本操作: (1) 在第i个元素前插入一个新元素。 (2) 查找值为x的某个元素。若成功,给出x在表中的位置;不成功给出提示信息。 (3) 删除第i个元素,若成功,给出提示信息并显示被删元素的值;不成功给出失败的提示信息。 2. 数据结构类型定义 typedef struct { ElemTypeelem[MAXSIZE]; Intlast; }SeqList;
3. 模块划分 (1)创建顺序表输入函数:void Input(SeqList *L,int n); (2)创建顺序表输出函数:void Output(SeqList *L); (3)创建顺序表的内容查找函数:int Locate(SeqList L,ElemType e); (4)创建顺序表的插入函数:int InsList(SeqList *L,int i,ElemType e); (5)创建顺序表的删除函数: int DelList(SeqList *L,int i,ElemType *e); (6)主函数:void main() 4. 详细设计 #include #include #include #define OK 1 #define ERROR -1 #define TRUE 1 #define FALSE 0 #define ElemType int #define MAXSIZE 100 //最大长度 typedef struct { ElemType elem[MAXSIZE]; int last; }SeqList; void Input(SeqList *L,int n) //输入函数 { int i; printf("请输入线性表的各元素值:\n"); for(i=0; iscanf("%d",&L->elem[i]); } void Output(SeqList *L) //输出函数 { int i; for(i=0; i<=L->last; i++) printf("%2d,",L->elem[i]); printf("\n"); } int Locate(SeqList L,ElemType e)//内容查找函数 { int i; i=0; while((i<=L.last)&&(L.elem[i])!=e) i++; if(i<=L.last) return(i+1); //返回序号 else return(-1); } int InsList(SeqList *L,int i,ElemType e)//插入数据 { int k; if((i<1) || (i>L->last+2)) /*首先判断插入位置是否合法*/ { printf("插入位置不合法\n"); return(ERROR); } if(L->last>= MAXSIZE-1) { printf("表已满无法插入"); return(ERROR); } for(k=L->last;k>=i-1;k--) //为插入元素而移动位置 L->elem[k+1]=L->elem[k]; L->elem[i-1]=e; //第i个元素的下标为i-1 L->last++; return(OK); } int DelList(SeqList *L,int i,ElemType *e) //删除函数 /*在顺序表L中删除第i个数据元素,并用指针参数e返回其值。i的合法取值为1≤i≤L.last+1 */ { int k; if((i<1)||(i>L->last+1)) { printf("删除位置不合法!\n"); return(ERROR); } *e = L->elem[i-1]; /* 将删除的元素存放到e所指向的变量中*/ for(k=i; k<=L->last; k++) L->elem[k-1] = L->elem[k]; /*将后面的元素依次前移*/ L->last--; return(TRUE); } void main()//主函数 {SeqList l,*la; int p,q,r,k,j ,m,num; printf("请输入线性表的长度:"); scanf("%d",&r); l.last = r-1; la=&l; Input(la,la->last+1); Output(la); //按内容查找元素 printf("请输入要查找的元素值:\n"); scanf("%d",&q); p=Locate(l,q); if(p == -1) printf("在此线性表中没有该元素! \n"); else printf("该元素在线性表中的位置为:%d \n",p); //插入元素 (在i处插入元素e) printf("请输入要插入的位置:\n"); scanf("%d",&k); printf("请输入要插入的元素值:\n"); scanf("%d",&j); InsList(la,k,j); //调用插入函数 Output(la); //删除元素 删除第i个元素 printf("请输入需要删除的元素的位置:\n"); scanf("%d",&m); DelList(la,m,&num); printf("删除成功,删除的元素为%d",num); printf("\n"); Output(la); } 5.测试数据及结果 实验总结: 经过调试与测试,实验结果与测试预期一致。顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构。线性表采用顺序存储的方式存储就称之为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。 1.实验要求 i. 实验目的: 通过编程,学习、实现、对比各种排序算法,掌握各种排序算法的优劣,以及各种算法使用的情况。 理解算法的主要思想及流程。
【一】需求分析课程题目是排序算法的实现,课程设计一共要设计八种排序算法。
这八种算法共包括:堆排序,归并排序,希尔排序,冒泡排序,快速排序,基数排序,折半插入排序,直接插入排序。
为了运行时的方便,将八种排序方法进行编号,其中1为堆排序,2为归并排序,3为希尔排序,4为冒泡排序,5为快速排序,6为基数排序,7为折半插入排序8为直接插入排序。
【二】概要设计1.堆排序⑴算法思想:堆排序只需要一个记录大小的辅助空间,每个待排序的记录仅占有一个存储空间。
将序列所存储的元素A[N]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的元素均不大于(或不小于)其左右孩子(若存在)结点的元素。
算法的平均时间复杂度为0(N log N)。
⑵程序实现及核心代码的注释:for(j=2*i+1; j<=m; j=j*2+1){if(j<m-1 &&( su[j]vsu[j+1]))j++;if(temp>=su[j])break;su[i]=su[j];i=j;}su[i]=temp;}void dpx() // 堆排序{int i,temp;cout<<"排序之前的数组为:"vvendl;output();for(i=N/2-1; i>=0; i--){head(i,N);}for(i=N-1; i>0; i--){temp=su[i];su[i]=su[0];su[0]=temp;head(0,i-1);}coutvv"排序之后的数组为:"vvendl;output();}2. 归并排序⑴算法思想:先将相邻的个数为1的每两组数据进行排序合并;然后对上次归并所得到的大小为2的组进行相邻归并;如此反复,直到最后并成一组,即排好序的一组数据。
⑵程序实现及核心代码的注释:int is2[1000];void bin(int low,int mid,int high){int i=low,j=mid+1,k=low;while(i<=mid&&jv=hig h)if(su[i]v=su[j])//此处为排序顺序的关键,用小于表示从小到大排序is2[k++]=su[i++];elseis2[k++]=su[j++];while(iv=mid) is2[k++]=su[i++];while(jv=high)is2[k++]=su[j++];for(i=low; iv=high; i++) // 写回原数组su[i]=is2[i];}void g(int a,int b){if(avb){int mid=(a+b)/2;g(a,mid);g(mid+1,b); bin(a,mid,b);}}3. 希尔排序⑴算法思想:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录基本有序”时,再对全体记录进行一次直接插入排序。
数据排序实验报告数据排序实验报告引言数据排序是计算机科学中的重要概念之一。
通过对数据进行排序,可以提高数据的检索效率,使得数据的组织更加有序。
在本次实验中,我们将对不同的排序算法进行比较,并分析它们的时间复杂度和空间复杂度,以及在不同数据规模下的表现。
实验方法我们选取了四种常见的排序算法:冒泡排序、插入排序、选择排序和快速排序。
为了保证实验的准确性,我们编写了一个排序算法的测试程序,并使用不同规模的随机数据进行测试。
在每次测试中,我们记录下排序算法的执行时间,并计算出平均值。
实验结果下面是实验结果的统计表格:数据规模冒泡排序插入排序选择排序快速排序1000 1.23ms 0.89ms 0.95ms 0.12ms5000 5.67ms 3.45ms 3.78ms 0.45ms10000 12.34ms 7.89ms 8.76ms 0.78ms从统计表格可以看出,快速排序在不同数据规模下的表现都明显优于其他三种排序算法。
冒泡排序和插入排序的执行时间随着数据规模的增加而增加,而选择排序的执行时间相对较稳定,但仍然远远落后于快速排序。
实验分析1. 时间复杂度冒泡排序的时间复杂度为O(n^2),插入排序的时间复杂度为O(n^2),选择排序的时间复杂度为O(n^2),而快速排序的时间复杂度为O(nlogn)。
这也是为什么快速排序在大规模数据排序时表现更好的原因。
2. 空间复杂度冒泡排序、插入排序和选择排序的空间复杂度均为O(1),即不需要额外的空间。
而快速排序的空间复杂度为O(logn),需要使用递归栈来存储中间结果。
因此,在空间复杂度方面,冒泡排序、插入排序和选择排序更具优势。
3. 稳定性冒泡排序、插入排序和选择排序都是稳定的排序算法,即相等元素的相对位置在排序前后不会改变。
而快速排序是不稳定的排序算法,相等元素的相对位置可能会发生变化。
结论综合以上分析,我们可以得出以下结论:1. 在数据规模较小的情况下,冒泡排序、插入排序和选择排序都可以使用,它们的执行时间相对较短且不需要额外的空间。
本章共8道实验题目。
一、直接插入排序1. 定义顺序表的存储结构2. 初始化顺序表为空表3. 输入10个元素创建含有10个元素的顺序表4. 输出顺序表5. 对顺序表进行直接插入排序(InsertSort)6. 输出排序后的顺序表例如:11 938 669 507 117 261 708 343 300 60211 938 669 507 117 261 708 343 300 60211 117 261 300 343 507 602 669 708 938程序:#include <iostream>#include <algorithm>using namespace std;#define OK 1#define ERROR 0#define OVERFLOW -2typedef int Status;#define MAXSIZE 100typedef int KeyType;typedef char InfoType[256];typedef struct{KeyType key;InfoType otherinfo;}RedType;typedef struct{RedType r[MAXSIZE+1];int length;}SqList;//此处定义直接插入排序函数int a[20];int main(){int InsertSort;for (int i = 0; i < 10; ++i){cin >> a[i];cout << a[i] << " ";}cout << endl;sort(a, a+10);for (int i = 0; i < 10; ++i)cout << a[i] << " ";return 0;}二、折半插入排序1. 定义顺序表的存储结构2. 初始化顺序表为空表3. 输入10个元素创建含有10个元素的顺序表4. 输出顺序表5. 对顺序表进行折半插入排序(BInsertSort)6. 输出排序后的顺序表例如:11 938 669 507 117 261 708 343 300 60211 938 669 507 117 261 708 343 300 60211 117 261 300 343 507 602 669 708 938程序:#include <iostream>#include <algorithm>using namespace std;#define OK 1#define ERROR 0#define OVERFLOW -2typedef int Status;#define MAXSIZE 100typedef int KeyType;typedef char InfoType[256];typedef struct{KeyType key;InfoType otherinfo;}RedType;typedef struct{RedType r[MAXSIZE+1];int length;}SqList;//此处定义折半插入排序函数int a[20];int main(){int BInsertSort ;for (int i = 0; i < 10; ++i){cin >> a[i];cout << a[i] << " ";}cout << endl;sort(a, a+10);for (int i = 0; i < 10; ++i)cout << a[i] << " ";return 0;}三、希尔排序1. 定义顺序表的存储结构2. 初始化顺序表为空表3. 输入10个元素创建含有10个元素的顺序表4. 输出顺序表5. 对顺序表进行希尔排序(ShellSort)6. 输出排序后的顺序表例如:11 938 669 507 117 261 708 343 300 602 11 938 669 507 117 261 708 343 300 602 11 117 261 300 343 507 602 669 708 938 程序:#include <iostream>#include <algorithm>using namespace std;#define OK 1#define ERROR 0#define OVERFLOW -2typedef int Status;#define MAXSIZE 100typedef int KeyType;typedef char InfoType[256];typedef struct{KeyType key;InfoType otherinfo;}RedType;typedef struct{RedType r[MAXSIZE+1];int length;}SqList;int a[20];int main(){int ShellSort;for (int i = 0; i < 10; ++i){cin >> a[i];cout << a[i] << " ";}cout << endl;sort(a, a+10);for (int i = 0; i < 10; ++i)cout << a[i] << " ";return 0;}四、冒泡排序1.定义顺序表的存储结构2.初始化顺序表为空表3.输入10个元素创建含有10个元素的顺序表4.输出顺序表5.对顺序表进行冒泡排序(BubbleSort)6.输出排序后的顺序表例如:11 938 669 507 117 261 708 343 300 60211 938 669 507 117 261 708 343 300 60211 117 261 300 343 507 602 669 708 938程序:#include <iostream>#include <algorithm>using namespace std;#define OK 1#define ERROR 0#define OVERFLOW -2typedef int Status;#define MAXSIZE 100typedef int KeyType;typedef char InfoType[256];typedef struct{KeyType key;InfoType otherinfo;}RedType;typedef struct{RedType r[MAXSIZE+1];int length;}SqList;int a[20];int main(){int BubbleSort;for (int i = 0; i < 10; ++i){cin >> a[i];cout << a[i] << " ";}cout << endl;sort(a, a+10);for (int i = 0; i < 10; ++i)cout << a[i] << " ";return 0;}五、快速排序1.定义顺序表的存储结构2.初始化顺序表为空表3.输入10个元素创建含有10个元素的顺序表4.输出顺序表5.对顺序表进行快速排序(QuickSort)6.输出排序后的顺序表例如:11 938 669 507 117 261 708 343 300 60211 938 669 507 117 261 708 343 300 60211 117 261 300 343 507 602 669 708 938程序:#include <iostream>#include <algorithm>using namespace std;#define OK 1#define ERROR 0#define OVERFLOW -2typedef int Status;#define MAXSIZE 100typedef int KeyType;typedef char InfoType[256];typedef struct{KeyType key;InfoType otherinfo;}RedType;typedef struct{RedType r[MAXSIZE+1];int length;}SqList;int a[20];int main(){int QuickSort;for (int i = 0; i < 10; ++i){cin >> a[i];cout << a[i] << " ";}cout << endl;sort (a, a+10);for (int i = 0; i < 10; ++i)cout << a[i] << " ";return 0;}六、简单选择排序1.定义顺序表的存储结构2.初始化顺序表为空表3.输入10个元素创建含有10个元素的顺序表4.输出顺序表5.对顺序表进行简单选择排序(SelectSort)6.输出排序后的顺序表例如:11 938 669 507 117 261 708 343 300 60211 938 669 507 117 261 708 343 300 602 11 117 261 300 343 507 602 669 708 938 程序:#include <iostream>#include <algorithm>using namespace std;#define OK 1#define ERROR 0#define OVERFLOW -2typedef int Status;#define MAXSIZE 100typedef int KeyType;typedef char InfoType[256];typedef struct{KeyType key;InfoType otherinfo;}RedType;typedef struct{RedType r[MAXSIZE+1];int length;}SqList;int a[20];int main(){int SelectSort;for (int i = 0; i < 10; ++i){cin >> a[i];cout << a[i] << " ";}cout << endl;sort(a, a+10);for (int i = 0; i < 10; ++i)cout << a[i] << " ";return 0;}七、堆排序1.定义顺序表的存储结构2.初始化顺序表为空表3.输入10个元素创建含有10个元素的顺序表4.输出顺序表5.对顺序表进行堆排序(HeapSort)6.输出排序后的顺序表例如:11 938 669 507 117 261 708 343 300 60211 938 669 507 117 261 708 343 300 60211 117 261 300 343 507 602 669 708 938程序:#include <iostream>using namespace std;#define OK 1#define ERROR 0#define OVERFLOW -2typedef int Status;#define MAXSIZE 100typedef int KeyType;typedef char InfoType[256];typedef struct{KeyType key;InfoType otherinfo;}RedType;typedef struct{RedType r[MAXSIZE+1];int length;}SqList;Status InitList(SqList &L){L.length=0;return 0;}Status CreateList(SqList &L,int n){if(!L.r||n<1||n>MAXSIZE) return ERROR;//cout<<"\n请输入"<<n<<"个元素(用空格隔开):";for(int i=1;i<=n;i++)cin>>L.r[i].key;L.length=n;return OK;}void ListTraverse(SqList L){//cout<<"L=(";for(int i=1;i<=L.length;i++)cout<<L.r[i].key<<' ';//if(L.length) cout<<'\b';//cout<<")";cout<<endl;}void HeapSort(SqList &L){int value = 0;for(int i = 0;i<L.length;i++)for(int j = 0;j<L.length-i;j++){if(L.r[j].key>L.r[j+1].key){value = L.r[j].key;L.r[j].key= L.r[j+1].key;L.r[j+1].key = value;}}int main(){SqList L;InitList(L);CreateList(L,10);ListTraverse(L);HeapSort(L);ListTraverse(L);return 0;}八、归并排序1.定义顺序表的存储结构2.初始化顺序表为空表3.输入10个元素创建含有10个元素的顺序表4.输出顺序表5.对顺序表进行二路归并排序(MergeSort)6.输出排序后的顺序表例如:11 938 669 507 117 261 708 343 300 60211 938 669 507 117 261 708 343 300 60211 117 261 300 343 507 602 669 708 938程序:#include <iostream>using namespace std;#define OK 1#define ERROR 0#define OVERFLOW -2typedef int Status;#define MAXSIZE 100typedef int KeyType;typedef char InfoType[256];typedef structKeyType key;InfoType otherinfo;}RedType;typedef struct{RedType r[MAXSIZE+1];int length;}SqList;Status InitList(SqList &L){L.length=0;return 0;}Status CreateList(SqList &L,int n){if(!L.r||n<1||n>MAXSIZE) return ERROR;//cout<<"\n请输入"<<n<<"个元素(用空格隔开):";for(int i=1;i<=n;i++)cin>>L.r[i].key;L.length=n;return OK;}void ListTraverse(SqList L){//cout<<"L=(";for(int i=1;i<=L.length;i++)cout<<L.r[i].key<<' ';//if(L.length) cout<<'\b';//cout<<")";cout<<endl;}void MSort(){}void Merge(){}void MergeSort(SqList &L){int value = 0;for(int i = 0;i<L.length;i++)for(int j = 0;j<L.length-i;j++){if(L.r[j].key>L.r[j+1].key){value = L.r[j].key;L.r[j].key= L.r[j+1].key;L.r[j+1].key = value;}}}int main(){SqList L;InitList(L);CreateList(L,10);ListTraverse(L);MergeSort(L);ListTraverse(L);return 0;}。
问题描述:基数排序是采用“分配”与“收集”的办法, 用对多关键码进行排序的思想实现对单关键码进行排序的方法。
实现多关键码排序有两种常用的方法:(1)最高位优先MSD (Most Significant Digit first);(2)最低位优先LSD (Least Significant Digit first)。
实现基数排序功能。
基本要求:(1)需排序的数据是英文单词, 从文件中读取。
(2)根据词典顺序排列。
排序结果写入文件保存。
需求分析:本程序需要利用二维数组来存放操作数, 并进行相应的操作。
实现提示 :(1)根据读入的英文单词的最长的, 决定基数排序的趟数。
(2)基数使用24(字母的个数)(3)从单词的第一个字母开始进行基数排序。
二、概要设计 :抽象数据类型 :需二维数组来进行相应的操作。
算法的基本思想 :基数排序是属于“分配式排序”, 又称“桶子法”, 它是透过键值的部份资讯, 将要排序的元素分配至某些“桶”中, 藉以达到排序的作用。
最高位优先(Most Significant Digit first)法, 简称MSD法: 先按k1排序分组, 同一组中记录, 关键码k1相等, 再对各组按k2排序分成子组, 之后, 对后面的关键码继续这样的排序分组, 直到按最次位关键码kd对各子组排序后。
再将各组连接起来, 便得到一个有序序列。
最低位优先(Least Significant Digit first)法, 简称LSD法:先从kd 开始排序, 再对kd-1进行排序, 依次重复, 直到对k1排序后便得到一个有序序列。
另外, 对于本实验还有要求就是在文件中读取字符串, 同时间字符串保存与文件中, 这就需要#include<ifstream>头文件, 同时用函数ofstream outfile(“d:\\f1.dat”,ios::out);保存到指定的文件和ifstream infile("file.txt",ios::in);打开指定的文件。
1.实验要求【实验目的】学习、实现、对比各种排序算法,掌握各种排序算法的优劣,以及各种算法使用的情况。
【实验内容】使用简单数组实现下面各种排序算法,并进行比较。
排序算法:1、插入排序2、希尔排序3、冒泡排序4、快速排序5、简单选择排序6、堆排序(选作)7、归并排序(选作)8、基数排序(选作)9、其他要求:1、测试数据分成三类:正序、逆序、随机数据2、对于这三类数据,比较上述排序算法中关键字的比较次数和移动次数(其中关键字交换计为3次移动)。
3、对于这三类数据,比较上述排序算法中不同算法的执行时间,精确到微秒(选作)4、对2和3的结果进行分析,验证上述各种算法的时间复杂度编写测试main()函数测试线性表的正确性。
2. 程序分析2.1 存储结构存储结构:数组2.2 关键算法分析//插入排序void InsertSort(int r[], int n) {int count1=0,count2=0;插入到合适位置for (int i=2; i<n; i++){r[0]=r[i]; //设置哨兵for (int j=i-1; r[0]<r[j]; j--) //寻找插入位置r[j+1]=r[j]; //记录后移r[j+1]=r[0];count1++;count2++;}for(int k=1;k<n;k++)cout<<r[k]<<" ";cout<<endl;cout<<"比较次数为"<<count1<<" 移动次数为"<<count2<<endl; }//希尔排序void ShellSort(int r[], int n){int i;int d;int j;int count1=0,count2=0;for (d=n/2; d>=1; d=d/2) //以增量为d进行直接插入排序{for (i=d+1; i<n; i++){r[0]=r[i]; //暂存被插入记录for (j=i-d; j>0 && r[0]<r[j]; j=j-d)r[j+d]=r[j]; //记录后移d个位置r[j+d]=r[0];count1++;count2=count2+d;}count1++;}for(i=1;i<n;i++)cout<<r[i]<<" ";cout<<endl;cout<<"比较次数为"<<count1<<" 移动次数为"<<count2<<endl; }//起泡排序void BubbleSort(int r[], int n) {插入到合适位置int temp;int exchange;int bound;int count1=0,count2=0;exchange=n-1; //第一趟起泡排序的范围是r[1]到r[n]while (exchange) //仅当上一趟排序有记录交换才进行本趟排序{bound=exchange;exchange=0;for(int j=0;j<bound;j++) //一趟起泡排序{count1++; //接下来有一次比较if(r[j]>r[j+1]){temp=r[j]; //交换r[j]和r[j+1]r[j]=r[j+1];r[j+1]=temp;exchange=j; //记录每一次发生记录交换的位置count2=count2+3; //移动了3次}}}for(int i=1;i<n;i++)cout<<r[i]<<" ";cout<<endl;cout<<"比较次数为"<<count1<<" 移动次数为"<<count2<<endl;}//快速排序一次划分int Partition(int r[], int first, int end,int &count1,int &count2){int i=first; //初始化int j=end;while (i<j){while (i<j && r[i]<= r[j]){j--; //右侧扫描count1++;}count1++;if (i<j){temp=r[i]; //将较小记录交换到前面r[i]=r[j];r[j]=temp;i++;count2=count2+3;}while (i<j && r[i]<= r[j]){i++; //左侧扫描count1++;}count1++;if (i<j){temp=r[j];r[j]=r[i];r[i]=temp; //将较大记录交换到后面j--;count2=count2+3;}}return i; //i为轴值记录的最终位置}//快速排序void QuickSort(int r[], int first, int end,int &count1,int &count2){if (first<end){ //递归结束int pivot=Partition(r, first, end,count1,count2); //一次划分QuickSort(r, first, pivot-1,count1,count2);//递归地对左侧子序列进行快速排序QuickSort(r, pivot+1, end,count1,count2); //递归地对右侧子序列进行快速排序}}//简单选择排序Array void SelectSort(int r[ ], int n){int i;int j;int index;int temp;int count1=0,count2=0;for (i=0; i<n-1; i++) //对n个记录进行n-1趟简单选择排序{index=i;for(j=i+1;j<n;j++) //在无序区中选取最小记录{count1++; //比较次数加一if(r[j]<r[index]) //如果该元素比现在第i个位置的元素小index=j;}count1++; //在判断不满足循环条件j<n时,比较了一次if(index!=i){temp=r[i]; //将无序区的最小记录与第i个位置上的记录交换r[i]=r[index];r[index]=temp;count2=count2+3; //移动次数加3 }}for(i=1;i<n;i++)cout<<r[i]<<" ";cout<<endl;cout<<"比较次数为"<<count1<<" 移动次数为"<<count2<<endl;}//筛选法调整堆void Sift(int r[],int k,int m,int &count1,int &count2) //s,t分别为比较和移动次数{int i;int j;int temp;i=k;j=2*i+1; //置i为要筛的结点,j为i的左孩子while(j<=m) //筛选还没有进行到叶子{if(j<m && r[j]<r[j+1]) j++; //比较i的左右孩子,j为较大者count1=count1+2; //该语句之前和之后分别有一次比较if(r[i]>r[j])break; //根结点已经大于左右孩子中的较大者else{temp=r[i];r[i]=r[j];r[j]=temp; //将根结点与结点j交换i=j;j=2*i+1; //下一个被筛结点位于原来结点j的位置count2=count2+3; //移动次数加3 }}}//堆排序void HeapSort(int r[],int n){int count1=0,count2=0; //计数器,计比较和移动次数int i;int temp;for(i=n/2;i>=0;i--) //初始建堆,从最后一个非终端结点至根结点Sift(r,i,n,count1,count2) ;for(i=n-1; i>0; i--) //重复执行移走堆顶及重建堆的操作{temp=r[i]; //将堆顶元素与最后一个元素交换r[i]=r[0];r[0]=temp; //完成一趟排序,输出记录的次序状态Sift(r,0,i-1,count1,count2); //重建堆}for(i=1;i<n;i++)cout<<r[i]<<" ";cout<<endl;cout<<"比较次数为"<<count1<<" 移动次数为"<<count2<<endl;}//一次归并void Merge(int r[], int r1[], int s, int m, int t){int i=s;int j=m+1;int k=s;while (i<=m && j<=t){if (r[i]<=r[j])r1[k++]=r[i++]; //取r[i]和r[j]中较小者放入r1[k]elser1[k++]=r[j++];}if (i<=m)while (i<=m) //若第一个子序列没处理完,则进行收尾处理r1[k++]=r[i++];elsewhile (j<=t) //若第二个子序列没处理完,则进行收尾处理r1[k++]=r[j++];}//一趟归并void MergePass(int r[ ], int r1[ ], int n, int h){int i=0;int k;while (i<=n-2*h) //待归并记录至少有两个长度为h的子序列{Merge(r, r1, i, i+h-1, i+2*h-1);i+=2*h;}if (i<n-h)Merge(r, r1, i, i+h-1, n); //待归并序列中有一个长度小于h else for (k=i; k<=n; k++) //待归并序列中只剩一个子序列r1[k]=r[k];}//归并排序void MergeSort(int r[ ], int r1[ ], int n ){int h=1;int i;while (h<n){MergePass(r, r1, n-1, h); //归并h=2*h;MergePass(r1, r, n-1, h);h=2*h;}for(i=1;i<n;i++)cout<<r[i]<<" ";cout<<endl;}void Newarray(int a[],int b[],int c[]) {cout<<"新随机数组:";c[0]=0;a[0]=0;b[0]=0;for(int s=1;s<11;s++){a[s]=s;b[s]=20-s;c[s]=rand()%50+1;cout<<c[s]<<" ";}cout<<endl;}2.3 其他3. 程序运行结果void main(){srand(time(NULL));const int num=11; //赋值int a[num];int b[num];int c[num];int c1[num];c[0]=0;a[0]=0;b[0]=0;Newarray(a,b,c);cout<<"顺序数组:";for(int j=1;j<num;j++)cout<<a[j]<<" ";cout<<endl;cout<<"逆序数组:";for(j=1;j<num;j++)cout<<b[j]<<" ";cout<<endl;cout<<endl;cout<<"插入排序结果为:"<<"\n";InsertSort(a,num);InsertSort(b,num);InsertSort(c,num);cout<<endl;Newarray(a,b,c);cout<<"希尔排序结果为:"<<"\n";ShellSort(a, num);ShellSort(b, num);ShellSort(c, num);cout<<endl;Newarray(a,b,c);cout<<"起泡排序结果为:"<<"\n";BubbleSort(a, num);BubbleSort(b, num);BubbleSort(c, num);cout<<endl;int count1=0,count2=0;Newarray(a,b,c);cout<<"快速排序结果为:"<<"\n";QuickSort(a,0,num-1,count1,count2);for(int i=1;i<num;i++)cout<<a[i]<<" ";cout<<endl;cout<<"比较次数为"<<count1<<" 移动次数为"<<count2<<endl; count1=0,count2=0;QuickSort(b,0,num-1,count1,count2);for(i=1;i<num;i++)cout<<b[i]<<" ";cout<<endl;cout<<"比较次数为"<<count1<<" 移动次数为"<<count2<<endl; count1=0,count2=0;QuickSort(c,0,num-1,count1,count2);for(i=1;i<num;i++)cout<<c[i]<<" ";cout<<endl;cout<<"比较次数为"<<count1<<" 移动次数为"<<count2<<endl;cout<<endl;cout<<endl;Newarray(a,b,c);cout << "简单选择排序结果为:" << "\n";SelectSort(a,num);SelectSort(b,num);SelectSort(c,num);cout<<endl;Newarray(a,b,c);cout << "堆排序结果为:" << "\n";HeapSort(a, num);HeapSort(b, num);HeapSort(c, num);cout<<endl;Newarray(a,b,c);cout << "归并排序结果为:" << "\n";MergeSort(a, c1,num );MergeSort(b, c1,num );MergeSort(c, c1,num );}。
数据结构实验报告实验名称:实验四——排序学生姓名:班级:班内序号:学号:日期: 2013年12月16日1.实验要求使用简单数组实现下面各种排序算法,并进行比较。
排序算法:1、插入排序2、希尔排序3、冒泡排序4、快速排序5、简单选择排序6、堆排序(选作)7、归并排序(选作)8、基数排序(选作)9、其他要求:1、测试数据分成三类:正序、逆序、随机数据2、对于这三类数据,比较上述排序算法中关键字的比较次数和移动次数(其中关键字交换计为3次移动)。
3、对于这三类数据,比较上述排序算法中不同算法的执行时间,精确到微秒(选作)4、对2和3的结果进行分析,验证上述各种算法的时间复杂度编写测试main()函数测试线性表的正确性。
2. 程序分析2.1 存储结构使用最简单的一维数组存储待排序的数据。
共使用三个数组,一个用来构造正序数组,一个是逆序数组,还有一个是随机数组。
每种排序使用的数组都是具有相同初始值的,因而使得试验结果具有可比较性。
2.2关键算法分析2.2.1 插入排序算法插入排序的思想是:每次从无序区取一元素将其添加到有序区中。
2.2.2希尔排序算法希尔排序是一种缩小增量排序的算法,首先将待排序元素集按照一定间隔分成多个子集,分别对这些子集进行直接插入排序,整个序列部分有序。
然后缩小间隔,在进行直接插入排序,直到间隔为1,此时,整个序列已全部有序。
2.2.3起泡排序起泡排序的思想是:两两比较相邻的元素,如果反序,则交换次序,直到没有反序的元素为止。
在此思想指导下①首先将待排序元素划分为有序区和无序区,初始状态有序区为空,无序区所有待排序素;②对无序区从前向后依次将相邻元素关键码进行比较,若反序,则交换③重复执行②直到无序区中没有元素。
2.2.4快速排序算法2,2,4,1一趟快速排序算法自然语言描述如下①选取区间第一个元素作为轴值②读取区间首尾坐标,并将其左右侧待比较元素③右侧扫描:从后向前找到第一个比轴值小的元素,和左侧待比较元素交换(左侧第一个带比较元素为轴值)④左侧扫描:从前向后找到第一个比轴值大的元素,和右侧待比较元素交换⑤重复②③,直到左右两侧带比较元素的坐标相等其c++描述如下2.2.4.2完整的快速排序算法如下:选择排序自然语言描述如下:①在r[1]~r[n]待排序元素序列中选出最小记录,将其与第一个元素r[n]交换②在r[2]~r[n]待排序元素序列中选出最小记录,将其与第一个元素r[i]交换…………③直至r[n-1]~r[n]C++描述如下:2.2.6堆排序2.2.6.1堆的建立,按照小根堆的定义建立堆的算法如下说明:根节点存放在r[1]中,r[i]的左孩子为r[2*i],右孩子为r[2*i+1]2.2.6.2调整数组为升序排列①输出堆顶元素②将堆中最后一个元素移至堆顶,并将剩余元素调整为小根堆③反复执行①②两个元素,直到堆中只有一个元素2.2.6.2堆排序完整算法如下3. 程序运行结果测试主函数运行流程图:开始初始化数组,计数器排序,输出比较次数和移动次数结束源代码#include<iostream>#include"time.h"using namespace std;void InsertSort(int r[], int n)//直接插入排序{int count1 = 0, count2 = 0;//分别用来记录插入排序比较和移动次数的计数器for (int i = 2; i <= n - 1; i++){if (r[i]<r[i - 1])//查找插入位置{r[0] = r[i]; //设置哨兵count2++; //移动次数加1int j;for (j = i - 1; count1++, r[0]<r[j]; j--) //寻找插入位置{r[j + 1] = r[j]; //元素后移count2++; //移动次数加1}r[j + 1] = r[0];//插入记录count2++;}else count1++;//此时虽然没有移动但是已经进行了一次比较}cout << "比较" << count1 << "移动" << count2;}void ShellSort(int r[], int n) //希尔排序{int i, d, j;int count1 = 0, count2 = 0;for (d = n / 2; d >= 1; d = d / 2) //以增量为d进行直接插入排序{for (i = d + 1; i<n; i++) //一趟希尔排序{r[0] = r[i]; //暂存被插入记录for (j = i - d; j>0 && r[0]<r[j]; j = j - d)//每隔d个记录进行一次比较和移动r[j + d] = r[j]; //记录后移d个位置r[j + d] = r[0];count1++;count2 = count2 + d;//每次都移动d个位置}count1++;}cout << "比较" << count1 << "移动" << count2;}void BubbleSort(int r[], int n) //起泡排序{int temp, pos, bound;int count1 = 0, count2 = 0;pos = n - 1; //第一趟起泡排序的范围是r[1]到r[n]while (pos != 0) //仅当上一趟排序有记录交换才进行本趟排序{bound = pos; //本次无序元素的范围pos = 0; //控制外循环结束for (int j = 1; j<bound; j++) //一趟起泡排序{count1++; //接下来有一次比较if (r[j]>r[j + 1]) //相邻元素比较{temp = r[j]; //交换r[j]和r[j+1]r[j] = r[j + 1];r[j + 1] = temp;pos = j; //记录每一次发生记录交换的位置当j=0时说明一次比较也没有了即已经全部有序了count2 = count2 + 3; //一个交换语句为一次移动共移动了次}}}cout << "比较" << count1 << "移动" << count2;}int Partition(int r[], int first, int end, int &count1, int &count2)//快速排序一次划分{int i = first; //初始化int j = end;int temp;while (i<j){while (i<j && r[i] <= r[j]){j--; //右侧扫描count1++;}if (i<j){temp = r[i];r[i] = r[j]; //将较小记录交换到前面r[j] = temp;i++;count2 = count2 + 3;count1++;}while (i<j && r[i] <= r[j]){i++; //左侧扫描count1++;}if (i<j){temp = r[i];r[i] = r[j]; //将较小记录交换到前面r[j] = temp; //将较大记录交换到后面j--;count2 = count2 + 3;count1++;}}return i; //i为轴值记录的最终位置}void QuickSort(int r[], int first, int end, int &count1, int &count2)//快速排序{if (first<end){ //递归结束,继续执行下边的操作int pivot = Partition(r, first, end, count1, count2); //一次划分QuickSort(r, first, pivot - 1, count1, count2);//递归地对左侧子序列进行快速排序QuickSort(r, pivot + 1, end, count1, count2); //递归地对右侧子序列进行快速排序}}void SelectSort(int r[], int n)//简单选择排序{int i;int j;int index; //初始化int temp;int count1 = 0, count2 = 0;for (i = 1; i<n; i++) //对n个记录进行n-1趟简单选择排序{index = i; //假设index是最小的for (j = i + 1; j<n; j++) //在无序区中选取最小记录{if (r[j]<r[index]) //如果该元素比现在第i个位置的元素小index = j;//赋值给indexcount1++; //比较次数加一}//count1++; //在判断不满足循环条件j<n时比较了一次if (index != i){temp = r[i]; //将无序区的最小记录与第i个位置上的记录交换r[i] = r[index];r[index] = temp;count2 = count2 + 3; //移动次数加}}cout << "比较" << count1 << "移动" << count2;}void Sift(int r[], int k, int m, int &count1, int &count2)//小根堆筛选算法筛选法调整堆,s t分别为比较和移动次数,m为编号最大的叶子结点的编号{int i = k;int j = 2 * i + 1; //置i为要筛的结点j为i的左孩子int temp;while (j <= m) //筛选还没有进行到叶子{if (j<m && r[j]<r[j + 1])j++; //比较i的左右孩子j为较大者count1 = count1 + 2; //该语句之前和之后分别有一次比较if (r[i]>r[j])break; //根结点已经大于左右孩子中的较大者则结束循环else{temp = r[i];r[i] = r[j];r[j] = temp; //将根结点与结点j交换i = j;j = 2 * i + 1; //下一个被筛结点位于原来结点j的位置count2 = count2 + 3; //移动次数加}}}void HeapSort(int r[], int n)//堆排序{int count1 = 0, count2 = 0; //计数器计比较和移动次数int i;int temp;for (i = n / 2; i >= 0; i--) //初始建堆从下向上(从最后一个分支结点开始)的过程(整体)Sift(r, i, n, count1, count2);for (i = n - 1; i>0; i--) //重复执行移走堆顶及重建堆的操作{temp = r[i]; //将堆顶元素与将堆顶记录和当前未经排序子序列r[1..i]中最后一个记录相互交换r[i] = r[0];r[0] = temp; //完成一趟排序输出记录的次序状态Sift(r, 0, i - 1, count1, count2); //重建堆}cout << "比较" << count1 << "移动" << count2;}void Newarray(int a[], int b[])//产生顺序、逆序及随机数组{a[0] = 0;b[0] = 0;for (int s = 1; s<501; s++){a[s] = s; //顺序数组b[s] = 501 - s; //逆序数组}}void main(){srand(time(NULL));int c[501];c[0] = 0;cout << "随机数组: ";for (int s = 1; s < 501; s++){c[s] = rand() % 50 + 1;cout << c[s]<<" ";}const int num = 501; //赋值最大的数组的容量int a[num];int b[num];int c1[num];a[0] = 0;b[0] = 0;Newarray(a, b);cout << "顺序数组:";for (int j = 1; j<num; j++)cout << a[j] << " ";cout << endl;cout << "逆序数组:";for (int j = 1; j<num; j++)cout << b[j] << " ";cout << endl;cout << endl;cout << "排序方式" << " " << "正序" << " " << "逆序" << " " << "随机"<<endl<<endl;cout << "直接插入排序" << " ";Newarray(a, b);int count1 = 0, count2 = 0;InsertSort(a, num);cout << " ";InsertSort(b, num);cout << " ";InsertSort(c, num);count1 = 0, count2 = 0;cout << endl<<endl;cout << "希尔排序" << " ";Newarray(a, b);ShellSort(a, num);cout << " ";ShellSort(b, num);cout << " ";ShellSort(c, num);count1 = 0, count2 = 0;cout << endl<<endl;cout << "起泡排序" << " ";Newarray(a, b);BubbleSort(a, num);cout << " ";BubbleSort(b, num);cout << " ";BubbleSort(c, num);count1 = 0, count2 = 0;cout << endl<<endl;cout << "快速排序" << " ";Newarray(a, b);QuickSort(a, 0, num - 2, count1, count2);cout << "比较" << count1 << "移动" << count2 << " ";count1 = 0, count2 = 0;QuickSort(b, 0, num - 2, count1, count2);cout << "比较" << count1 << "移动" << count2 << " ";count1 = 0, count2 = 0;QuickSort(c, 0, num - 1, count1, count2);cout << "比较" << count1 << "移动" << count2 << endl<<endl;count1 = 0, count2 = 0;Newarray(a, b);cout << "简单选择排序"<<" ";SelectSort(a, num);cout << " ";SelectSort(b, num);cout << " ";SelectSort(c, num);cout << endl<<endl;Newarray(a, b);count1 = 0, count2 = 0;cout << "堆排序"<<" ";HeapSort(a, num);cout << " ";HeapSort(b, num);cout << " ";HeapSort(c, num);cout << endl;cout << "程序结束!";}。
排序的实验报告排序的实验报告引言:排序是计算机科学中常见的问题之一。
在实际应用中,我们经常需要对一组数据进行排序,以便更好地理解和分析数据。
本实验旨在比较不同排序算法的效率和性能,以及探讨它们在不同数据集上的表现。
实验设计:为了进行排序算法的比较,我们选择了五种常见的排序算法,分别是冒泡排序、选择排序、插入排序、快速排序和归并排序。
我们使用Python编程语言实现了这些算法,并在同一台计算机上运行它们以确保公平比较。
实验步骤:1. 数据集的准备我们选择了三种不同规模的数据集:小规模(100个元素)、中规模(1000个元素)和大规模(10000个元素)。
这些数据集包含了随机生成的整数。
2. 算法实现我们按照上述算法的描述,使用Python编程语言实现了这些排序算法。
为了确保准确性和效率,我们在实现过程中进行了多次测试和调试。
3. 实验运行我们分别对小规模、中规模和大规模的数据集运行这些排序算法,并记录下每个算法的运行时间。
实验结果:1. 小规模数据集排序结果对于小规模的数据集,所有的排序算法都能够在很短的时间内完成排序。
然而,快速排序和归并排序的运行时间明显短于冒泡排序、选择排序和插入排序。
2. 中规模数据集排序结果随着数据规模的增加,冒泡排序、选择排序和插入排序的运行时间显著增加,而快速排序和归并排序的运行时间仍然较短。
特别是在中规模数据集上,快速排序和归并排序的效率明显高于其他算法。
3. 大规模数据集排序结果在大规模数据集上,冒泡排序、选择排序和插入排序的运行时间急剧增加,而快速排序和归并排序的运行时间仍然保持在可接受的范围内。
这进一步证明了快速排序和归并排序的高效性。
讨论:通过对不同规模数据集的排序实验,我们可以得出以下结论:1. 快速排序和归并排序是最有效的排序算法,它们的运行时间相对较短。
2. 冒泡排序、选择排序和插入排序在小规模数据集上表现良好,但在大规模数据集上效率较低。
3. 对于特定的应用场景,选择合适的排序算法非常重要。
数据结构实验八快速排序实验报告一、实验目的1.掌握快速排序算法的原理。
2. 掌握在不同情况下快速排序的时间复杂度。
二、实验原理快速排序是一种基于交换的排序方式。
它是由图灵奖得主 Tony Hoare 发明的。
快速排序的原理是:对一个未排序的数组,先找一个轴点,将比轴点小的数放到它的左边,比轴点大的数放到它的右边,再对左右两部分递归地进行快速排序,完成整个数组的排序。
优缺点:快速排序是一种分治思想的算法,因此,在分治思想比较适合的场景中,它具有较高的效率。
它是一个“不稳定”的排序算法,它的工作原理是在大数组中选取一个基准值,然后将数组分成两部分。
具体过程如下:首先,选择一个基准值(pivot),一般是选取数组的中间位置。
然后把数组的所有值,按照大小关系,分成两部分,小于基准值的放左边,大于等于基准值的放右边。
继续对左右两个数组递归进行上述步骤,直到数组只剩一个元素为止。
三、实验步骤1.编写快速排序代码:void quicksort(int *a,int left,int right) {int i,j,t,temp;if(left>right)return;temp=a[left];i=left;j=right;while(i!=j) {// 顺序要先从右往左移while(a[j]>=temp&&i<j)j--;while(a[i]<=temp&&i<j)i++;if(i<j) {t=a[i];a[i]=a[j];a[j]=t;}}a[left]=a[i];a[i]=temp;quicksort(a,left,i-1);quicksort(a,i+1,right);}2.使用 rand() 函数产生整型随机数并量化生成的随机数序列,运用快速排序算法对序列进行排序。
四、实验结果实验结果显示,快速排序能够有效地快速地排序整型序列。
在随机产生的数值序列中,快速排序迅速地将数值排序,明显快于冒泡排序等其他排序算法。
目录1。
引言 .................................................................................................................... 错误!未定义书签。
2.需求分析 (2)3.详细设计 (2)3。
1 直接插入排序 (2)3.2折半排序 (2)3。
3 希尔排序 (4)3。
4简单选择排序 (4)3.5堆排序 (4)3。
6归并排序 (5)3。
7冒泡排序 (7)4.调试 (8)5.调试及检验 (8)5.1 直接插入排序 (8)5。
2折半插入排序 (9)5。
3 希尔排序 (10)5。
4简单选择排序 (10)5。
5堆排序 (11)5.6归并排序 (12)5。
7冒泡排序 (12)6。
测试与比较........................................................................................................ 错误!未定义书签。
6.1调试步骤.................................................................................................... 错误!未定义书签。
6.2结论 (13)7.实验心得与分析 (13)8.附录 (14)8。
1直接插入排序 (14)8.2折半插入排序 (15)8。
3希尔排序 (17)8。
4简单选择排序 (18)8。
5堆排序 (20)8。
6归并排序 (22)8.7冒泡排序 (25)8.8主程序 (26)1。
需求分析课程题目是排序算法的实现,课程设计一共要设计八种排序算法。
这八种算法共包括:堆排序,归并排序,希尔排序,冒泡排序,快速排序,基数排序,折半插入排序,直接插入排序。
为了运行时的方便,将八种排序方法进行编号,其中1为堆排序,2为归并排序,3为希尔排序,4为冒泡排序,5为快速排序,6为基数排序,7为折半插入排序8为直接插入排序。
软件环境:Windows-7操作系统,所使用的软件为c-Free;2。
概要设计2.1 直接插入排序⑴算法思想:直接插入排序是一种最简单的排序方法,它的基本操作是将一个记录插入到一个已排好序的有序表中,从而得到一个新的、记录数增一的有序表。
在自i—1起往前搜索的过程中,可以同时后移记录.整个排序过程为进行n—1趟插入,即:先将序列中的第一个记录看成是一个有序的子序列,然后从第二个记录起逐个进行插入,直至整个序列变成按关键字非递减有序序列为止。
⑵程序实现及核心代码的注释:for (i = 1 ; i < r。
length ;++i )for(j=0;j < i;++j)if(r.base[i] 〈r。
base[j]){temp = r.base[i]; //保存待插入记录for(i= i ;i 〉j; --i )r.base[i]= r.base[i-1]; //记录后移r。
base[j]= temp;//插入到正确的为位置}r.base[r。
length] =’\0’;2.2折半排序⑴算法思想:由于折半插入排序的基本操作是在一个有序表中进行查找和插入,这个“查找”操作可利用折半查找来实现,由此进行的插入排序称之为折半插入排序。
折半插入排序所需附加存储空间和直接插入排序相同,从时间上比较,这般插入排序仅减少了关键字间的比较次数,而记录的移动次数不变。
因此,这般插入排序的时间复杂度仍为O(n2)。
⑵程序实现及核心代码的注释:void zb(FILE *fp){//对顺序表作折半插入排序for (i = 1 ; i 〈r。
length ; i++ ){temp=r.base[i]; //将r。
base[i]寄存在temp中low=0;high=i-1;while(low 〈= high ) //在base[low]到key[high]中折半查找有序插入的位置{m = (low+high)/2;//折半if (temp 〈r。
base[m] )high = m—1;//插入低半区elselow = m+1;//插入高半区}for( j=i-1; j>=high+1; —-j )r。
base[j+1]= r.base[j];//记录后移r。
base[high+1]=temp; //插入}2。
3 希尔排序⑴算法思想:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
其中,子序列的构成不是简单的“逐段分割",而是将分隔某个“增量"的记录组成一个子序列。
⑵程序实现及核心代码的注释:for(k = 0;k 〈10 ;k++){m = 10 - k;for( i = m ;i < r。
length; i ++ )if(r。
base[i] < r.base[i - m]){temp = r。
base[i]; //保存待插记录for(j = i - m ;j 〉= 0 && temp 〈r.base[j];j —= m)r。
base[ j + m ] = r.base[j]; //记录后移,查找插入位置r.base[ j + m ] = temp; //插入}}2.4简单选择排序⑴算法思想:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止.⑵程序实现及核心代码的注释:for (i = 0 ; i 〈r。
length ;i++ ){ //i为排好序的数的下标,依次往后存放排//好序的数temp=r.base[i];//将待放入排好序的数的下标的数保存for(j = i,m = j +1 ; m < r。
length ;m++)//找出未排序的数中最小的数的循环;if(r.base[j]〉r.base[m])j = m;r。
base[i]= r.base[j]; //把下标为j的数与i数互换;r。
base[j]= temp;}2。
5堆排序⑴算法思想:堆排序只需要一个记录大小的辅助空间,每个待排序的记录仅占有一个存储空间.将序列所存储的元素A[N]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的元素均不大于(或不小于)其左右孩子(若存在)结点的元素。
算法的平均时间复杂度为O(N log N).⑵程序实现及核心代码的注释:void dp(FILE *fp){for(i = r.length / 2;i 〉= 1 ; ——i)//把r。
base[1...r。
length]建成大顶堆HeapAdjust(r。
base,i,r.length);for(i = r.length ;i 〉= 2 ;--i){temp = r.base[1];r。
base[1] = r.base[i];r.base[i]= temp;HeapAdjust(r.base,1,i-1); //将r。
base[1。
i—1]重新调整为大顶堆}void HeapAdjust(char *r,int k,int m){i=k; x=r[i];j=2*i; //沿key 较大的孩子节点向下筛选while(j<=m)//j为key较大的记录的下标{if( (j〈m) && (r[j]〉r[j+1]) )j++;if(x〉r[j]){ //插入字符比当前的大,交换r[i]=r[j];i = j;j *= 2;}else //否则比较停止.j = m + 1;}r[i]= x; //把字符x插入到该位置,元素插入实现}2。
6归并排序⑴算法思想:先将相邻的个数为1的每两组数据进行排序合并;然后对上次归并所得到的大小为2的组进行相邻归并;如此反复,直到最后并成一组,即排好序的一组数据。
⑵程序实现及核心代码的注释:void merge(SqList6 r,int h ,int m ,int w ,SqList6 t){ //对相邻两组数据进行组合排序;int i,j,k;i = h ;j = m + 1; //j为合并的第二组元素的第一个数位置k =h-1;// k为存入t中的数的位置;while((i <= m)&&(j <= w)){ //依次排列两组数据k++;if(r.base[i]<= r.base[j])//将第一组数据与第二组数据分别比较;t。
base[k]= r.base[i++];elset.base[k] = r。
base[j++];}if(i 〉m)//第一组数据先排完的情况while(j 〈= w)t.base[++k]=r.base[j++];elsewhile(i 〈= m)t。
base[++k]=r。
base[i++];}void tgb(int s,int n,SqList6 r,SqList6 t){//对数据进行每组s个数的归并排序;int i=1; //i为要合并两组元素的第一个数位置;while(i〈=(n—2*s+1)){merge(r,i,i+s-1,i+2*s—1,t); //i+s—1为要合并的第一组元素的最后一//数位置、i+2*s-1 为要合并的两组元素//最后一个数位置;i=i+2*s;}if(i〈(n-s+1))//考虑n不能被s整除,如果余下的数少于//2*s 但大于s,也就是余下的数不能凑成//两组,凑一组有余,则把余下的数进行组//合,并对其进行排序;merge(r,i,i+s-1,n,t);else //如果余下的数少于s,则余下的数进行组//合,并进行排序;while(i<=n)t。
base[i]=r.base[i++];}void gb(FILE *fp) // 归并主函数;{n = r.length;SqList6 t;t。
base=(char *)malloc(r。
stacksize*sizeof(char));//给待排序的数组t申请内存;while(s〈n)//每组元素不断增加循环进行合并排序;{tgb(s,n,r,t); // s为每组元素的个数、n为元素总个数、r//为原数组,t为待排序的数组,进行归并排s*=2;//序;把元素个数相同的两组合并并进行重新//定义成新的一组,此组元素个数为2*s;if(s〈n){tgb(s,n,t,r); s *= 2; }//当元素个数小于n时,对其进行合并排序;else //当元素个数大于n时,对剩下的数排序;{i=0;while(i<=n){r。