任务要求
利用随机函数产生不少于30000个随机整数,利用直接插入排序、起泡排序、选择排序、快速排序、堆排序、归并排序等排序方法进行排序,并统计每一种排序上机所花费的时间。
系统功能
本系统通过rand函数产生相应的随机数,并键盘输入相应的指令来选择相应的排序方式,如直接插入排序、起泡排序、选择排序、快速排序、堆排序、归并排序等。同时利用函数计算不同排序方式排序所需要的时间。
系统功能
数据的逻辑结构为线性表,直接插入排序的存储结构是顺序存储结构;起泡排序的存储结构是顺序存储结构;选择排序的存储结构是顺序存储结构;快速排序的存储结构是顺序存储结构;堆排序的存储结构是顺序存储结构;归并排序的存储结构是顺序存储结构。
各排序算法
(1)直接插入排序
算法思想:在一个已排好序的记录子集的基础上,每一步将下一个待排序的记录有序地插入到已排好序的记录子集中,直到将所有待排记录全部插入为止。
数据类型定义:整数类型
函数接口:函数名:InsertSort
参数:SeqList L
函数功能说明:直接插入排序就是把待排序列分为已排好序和未排序的两个序列,每次从为排序的序列中取一个元素插入到已经排好序的序列中并进行交换实现有序,直到未排序的序列中没有元素。对于每次插入:从已排好序的序列的最后一个元素开始比较,如果插入的元素优先级低于比较的元素,就交换二者的顺序,直到插入元素找到合适位置。
(2)冒泡排序
算法思想:起泡排序的过程很简单,首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序(即r[1].key>r[2].key),则将两个记录交换之,然后比较第二个记录和第三个记录的关键字,若为逆序(即r[2].key>r(3].key),则将两个记录交换之,以此类推,直到第n-1个记录和第n个记录的关键字进行比较为止。
数据类型定义:整数类型
函数接口:函数名:maopao
参数:SeqList L
函数功能说明:进行N-1次循环,在第k次循环中从0开始到N-k-1每次比较相邻的两个元素,看是否需要交换。平均时间复杂度是O(n2)
(3)快速排序
算法思想:(1)先从数列中取出一个数作为基准数(该记录称为枢轴)。(2)将比基准数大的全放在它的右边,小于或等于基准数的全放到它的左边。(3)再对左右两部分重复第(2)步,直到各区间只有一个数,达到整个序列有序。
数据类型定义:整数类型
函数接口:函数名:QuickSort
参数:SeqList L, int low, int high
函数功能说明:每次取未排序的序列中的一个元素(称为主元)把未排序的序列分成两个子序列,其中一个全部小于主元,另一个全部大于主元,然后递归地进行这样的排序。
(4)选择排序
算法思想:首先,在待排序序列中选择出最小的记录,然后将这个最小的数据元素与第一个记录交换,第一个记录到位,这叫做第一趟排序;第二趟,就是从第二个记录到最后一个记录中选择最小的记录,之后将最小的记录以第二个记录交换,第二个纪录到位;以此类推,进行n-1趟,序列就有序了。
数据类型定义:整数类型
函数接口:函数名:SelectSort
参数:SeqList L
函数功能说明:简单选择排序就是每次都选出未处理的元素中最小或最大的元素与未处理部分的第一个元素交换,直到有序。 显然,要想知道是否到达有序,总要进行完所有的比较,也就是无论这个数组的有序性怎样,都要比较n(n-1)/2次,时间复杂度为O(n2) 。
(5)堆排序
算法思想:利用堆(小顶堆)进行排序的过程,首先把待排序序列(R1,R2,…,R)转换成一个堆。这时,根结点具有最小值,输出根结点(可以将其与堆数组中的末尾元素交换,此时末尾元素就是最小值),然后将剩下的n-1个结点重新调整为一个堆。反复进行下去,直到只剩下一个结点为止。
数据类型定义:整数类型
函数接口:函数名:HeapAdjust
参数:SeqListL,int s,int m
函数功能说明:堆排序就是利用堆(优先队列)对序列进行排序,因为优先级最高的元素永远在堆顶,所以我们可以一直取堆顶元素然后重新生成堆直到有序。
(6)归并排序
算法思想:在待排序的原始记录序列R[s…t]中取一个中间位置(s+t)/2,先分别对子序列R[s…(s+t)/2]和R[(s+t)/2+1…t]进行归并排序,然后调用合并算法便可实现整个序列R[s…t]成为记录的有序序列。
数据类型定义:整数类型
函数接口:函数名:MergeArray
参数:SeqList*L,int low,int mid,int high
函数功能说明:归并排序就是根据归并操作的原理,把序列中的N个元素看成N个有序的子序列,每次合并两个相邻有序子序列,直到剩下一个长度为N的 序列,即为原序列排好序后的有序序列。
代码
- #define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include<assert.h>
#include<malloc.h>
#include <time.h>//计时
//#ifndef _CLOCK_T_DEFINED
//typedef long clock_t;
//#define _CLOCK_T_DEFINED
//#endif
#define MAX_SIZE 100000
typedef struct SeqList
{
int *r;//r[0]闲置
int length;//顺序表总长度
}SeqList;
enum OP
{
EXIT,
INSERT,
BUBBLE,
QUICK,
SELECT,
STACK,
MERGE,
};
//建立并初始化线性表
void InitSeqList(SeqList* L)
{
assert(L);//检验指针有效性
L->r = (int *)malloc(MAX_SIZE*sizeof(int));//动态分配空间
if (!L->r)
{
printf("开辟空间失败!");
return;
}
L->length = 0;
}
//产生随机数并显示在界面上
void CreateShow(SeqList* L)
{
assert(L);
int i = 0, n;
printf("请输入要排序的元素个数>");
scanf("%d", &n);
for (; i <= n; i++)
{
L->r[i] = rand();//产生随机数
}
printf("\n");
printf("随机产生了%d个随机数,它们分别是>\n", n);
for (i = 1; i <= n; i++)
{
printf("%8d ", L->r[i]);
}
printf("\n");
L->length = n;
}
//打印出排序后的数据
void PrintSeqList(SeqList* L)
{
assert(L);
printf("数据个数为>%d\n", L->length);
printf("排序后的数据为(从小到大进行了排序)>\n");
for (int i = 1; i <= L->length; i++)
{
printf("%8d ", L->r[i]);
}
printf("\n");
}
//交换两个数
void swap(int* num1, int* num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
} //插入排序 void InsertSort(SeqList *L) { int i,j;
assert(L); if (L->length == 0)
{
printf("需要排序的数据为空!");
return;
} for(i=2;i<=L->length;++i) if(L->r[i]<L->r[i-1])
//当“<”时,才需将r[i]插入有序表 { L->r[0]=L->r[i];
//将带插入记录复制为哨兵 j=i-1; while(L->r[0]<L->r[j]) {
L->r[j+1]=L->r[j]; //记录后移
j--; } L->r[j+1]=L->r[0]; //插入到正确位置 } } //冒泡排序 void maopao(SeqList *L) { for(int i=0;i<L->length - 1;i++)
{ for(int j=0;j<L->length - i;j++) { if(L->r[i] > L->r[i +
1]) { swap(&L->r[i], &L->r[i + 1]);
} } } } //快速排序
void QuickSort(SeqList* L, int low, int high)
{
assert(L);
int mid;
int left = low;
int right = high;
if (L->length == 0)
{
printf("要排序的数据为空!");
return;
}
mid = L->r[low - (low - high) / 2];//选取的参照中间值
do
{
while (L->r[left] < mid && left < high)//从左到右找比mid大的元素
left++;
while (L->r[right] > mid && right > low)//从右到左找比mid小的元素
right--;
if (left <= right)//若找到且满足条件,则交换
{
swap(&L->r[left++], &L->r[right--]);
}
} while (left <= right);
if (left < high)
QuickSort(L, left, high);//运用递归
if (low < right)
QuickSort(L, low, right);
} //选择排序 void SelectSort(SeqList *L) { assert(L); int i; int k;
for(i=1;i<L->length;++i) //选择第i个小的记录,并交换到位 { int j=i;
//j用于记录最小元素的位置 for(k=i+1;k<=L->length;k++)
//在数组中选择key最小的元素 if(L->r[k]<L->r[j])
j=k;
if(i!=j) //第i个小的记录L->r[j]与第i个记录交换
{
swap(&L->r[i], &L->r[j]);
} } } //堆排序 void HeapAdjust(SeqList*L,int s,int m)//调整L->r[s]的关键字,使L->r[s-m]成为大顶堆 { assert(L); int i; L->r[0] =
L->r[s]; for(i=2*s;i<=m;i*=2)//沿数据较大的孩子结点向下筛选 { if(i<m &&
(L->r[i] < L->r[i+1]))//i为数据较大的记录下标 i++; if(L->r[0] >=
L->r[i])//L->r[0]插入在s位置上
break; L->r[s] = L->r[i]; s=i; } L->r[s] = L->r[0];//插入新数据 }
void HeapSort(SeqList*L) { assert(L); int i; if (L->length == 0)
{ printf("没有数据!"); return ; } for(i = L->length /2;i>0;i--)
HeapAdjust(L,i,L->length); for(i = L->length;i>1;i--) {
swap(&L->r[1],&L->r[i]);//将堆顶记录和当前未经排序的子序列L->r[l..i]中最后一个记录互换
HeapAdjust(L,i,i-1);//将L->r[l..i-1] 重整调整为大顶堆 } } //归并排序函数的具体实现
void MergeArray(SeqList*L,int low,int mid,int high) { assert(L);
int i,j,k,len1,len2; int *front,*back; len1 = mid-low+1;//前一部分的长度
len2 = high-mid;//后一部分的长度 front =
(int*)malloc(len1*sizeof(int));//申请两个空间存放排好的数据 back =
(int*)malloc(len2*sizeof(int)); //将数组转入两个新空间中 for(i=0;i<len1;i++)
front[i] = L->r[low+i]; for(j=0;j<=len2;j++) back[j] =
L->r[mid+j+1]; //合并元素 i=0; j=0; k=low; while(i<len1&&j<len2)
{//L->r[]中依次放入两个数组中较小的数 if(front[i]<back[j])
L->r[k++]=front[i++]; else L->r[k++]=back[j++]; } //将剩余元素合并
while(i<len1) L->r[k++]=front[i++]; while(j<len2)
L->r[k++]=back[j++]; } //归并函数排序函数的具体实现 void
MergeSort(SeqList*L,int low,int high) { assert(L); int middle;
if(L->length == 0) { printf("要排序的数据为空!"); return; }
if(low<high) { middle=low-(low-high)/2;
MergeSort(L,low,middle);//将前面一部分用递归的方法排序
MergeSort(L,middle+1,high);//将后面一部分用递归的方法排序
MergeArray(L,low,middle,high);//再将两个有序数列合并 } } //主菜单 void menu()
{
printf("\n\t*****************算法排序比较系统****************");
printf("\n\t-------------------------------------------------\n");
printf("\t*********** 1、直接插入排序 ***********\n");
printf("\t*********** 2、冒泡排序 ***********\n");
printf("\t*********** 3、快速排序 ***********\n");
printf("\t*********** 4、选择排序 ***********\n");
printf("\t*********** 5、堆排序 ***********\n");
printf("\t*********** 6、归并排序 ***********\n");
printf("\t*********** 0、退出系统 ***********\n");
}
int main()
{ SeqList L;
srand((unsigned int)time(NULL));
InitSeqList(&L);//初始化L
int n = 1;
clock_t start, end; //clock_t用于计时开始时间和结束时间
while (n)
{
menu();
printf("请选择你要排序的方式(数字1~6)或退出系统(数字0)>");
scanf("%d", &n);
switch (n)
{
case INSERT:
start = clock();
CreateShow(&L);
InsertSort(&L);
end = clock();
PrintSeqList(&L);
printf("插入排序时间是:%f毫秒\n", (float)(end - start));
break;
case BUBBLE:
start = clock();
CreateShow(&L);
maopao(&L);
end = clock();
PrintSeqList(&L);
printf("插入排序时间是:%f毫秒\n", (float)(end - start));
break;
case QUICK:
start = clock();
CreateShow(&L);
QuickSort(&L, 1, L.length);
end = clock();
PrintSeqList(&L);
printf("插入排序时间是:%f毫秒\n", (float)(end - start));
break;
case SELECT:
start = clock();
CreateShow(&L);
SelectSort(&L);
end = clock();
PrintSeqList(&L);
printf("插入排序时间是:%f毫秒\n", (float)(end - start));
break;
case STACK:
start = clock();
CreateShow(&L);
HeapSort(&L);
end = clock();
PrintSeqList(&L);
printf("插入排序时间是:%f毫秒\n", (float)(end - start));
break;
case MERGE:
start = clock();
CreateShow(&L);
MergeSort(&L, 1, L.length);
end = clock();
PrintSeqList(&L);
printf("插入排序时间是:%f毫秒\n", (float)(end - start));
break;
case EXIT:printf("感谢使用本系统,欢迎下次使用!"); break;
default:printf("您输入的序号错误!请重新选择>\n"); break;
}
}
system("pause");
return 0;
}