利用随机函数产生30000个随机整数,利用插入排序、起泡排序、选择排序、快速排序、堆排序、归并排序等排序方法进行排序,并且统计每一种排序上机所花费的时间。
1、折半插入排序:插入排序的基本插入是在一个有序表中进行查找和插入,这个查找可利用折半查找来实现,即为折半插入排序。
2、起泡排序:首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序,则将两个记录交换,然后比较第二个记录和第三个记录的关键字。依此类推,直到第N-1和第N个记录的关键字进行过比较为止。上述为第一趟排序,其结果使得关键字的最大纪录被安排到最后一个记录的位置上。然后进行第二趟起泡排序,对前N-1个记录进行同样操作。一共要进行N-1趟起泡排序。
3、快速排序:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,已达到整个序列有序。
4、选择排序:通过N-1次关键字间的比较,第i趟排序是后面N-i+1(i=1,2,3,4,........n-1)个元素中选择一个值最小的元素与该 N-i+1个元素的最前门的那个元素交换位置,即与整个序列的第 i 个元素交换位置。如此下去,直到 i = n - 1,排序结束。简单说就是从N-I+1个记录中选出关键字最小的记录,并和第I(1<=I<=N)个记录交换。
5、堆排序:在堆排序的算法中先建一个大顶堆,既先选得一个关键字作为最大的记录并与序列中最后一个记录交换,然后对序列中前N-1记录进行选择,重新将它调整成一个大顶堆,如此反复直到排序结束。
6、归并排序:归并排序算法采用的是分治算法,即把两个(或两个以上)有序表合并成一个新的有序表,即把待排序的序列分成若干个子序列,每个子序列都是有序的,然后把有序子序列合并成整体有序序列,这个过程也称为2-路归并。
代码如下所示
头文件为:
#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,
BININSERT,
BUBBLE,
QUICK,
SELECT,
STACK,
MERGE,
};
主函数文件为:
#include "SeqList.h"
//建立并初始化线性表
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)
{
assert(L);
int i, j;
if (L->length == 0)
{
printf("需要排序的数据为空!");
return;
}
for (i = 2; i <= L->length; i++)
{
if (L->r[i] < L->r[i - 1])//将L->r[i]插入有序表
{
//分析
// 2 3 8 7 9 5 10(选择r[i]=5,i=6)
//5 2 3 8 7 9 10
//5 2 3 8 7 9 10
//5 2 3 8 7 9 10(大于5的数都后移)
// 2 3 5 8 7 9 10
L->r[0] = L->r[i];//设置监视哨
L->r[i] = L->r[i - 1];
for (j = i - 2; L->r[0] < L->r[j]; j--)
{
L->r[j + 1] = L->r[j];//大于将要插入数的数后移
}
L->r[j + 1] = L->r[0];//插入到正确位置
}
}
}
//折半插入排序
void BinInsert(SeqList* L)
{
assert(L);
int i, j, mid, low, high;
if (L->length == 0)
{
printf("需要排序的数据为空!");
return;
}
for (i = 2; i <= L->length; i++)
{//折半查找
//分析
// 2 3 8 7 9 5 10(选择r[i]=5,i=6)
//5 2 3 8 7 9 10
//5 2 3 8 7 9 10(折半查找结束后,low为2,high为3)
//5 2 3 8 7 9 10(大于5的数8、7、9都后移)
// 2 3 5 8 7 9 10
L->r[0] = L->r[i];//将L->r[0]暂存在L->r[0]
low = 1;
high = i - 1;
while (low <= high)
{
mid = low - (low - high) / 2;
if (L->r[0] < L->r[mid])
{
high = mid - 1;//插入到低半部分
}
else
{
low = mid + 1;//插入到高半部分
}
}
for (j = i - 1; j >= high + 1; j--)
{
L->r[j + 1] = L->r[j];
}
L->r[high + 1] = L->r[0];//将要插入的数据插入
}
}
//冒泡排序
void BubbleSort(SeqList* L)
{
assert(L);
int i, j, flag;//冒泡排序的优化就是定义一个标志位flag,接近有序时停止冒泡
if (L->length == 0)
{
printf("需要排序的数据为空!");
return;
}
for (j = 1; j <= L->length - 1; j++)//总共比较L->length-1趟
{
for (i = 1; i <= L->length - j; i++)//每一趟冒泡出一个最大数
{
flag = 0;
if (L->r[i] > L->r[i + 1])
{//交换两个数
swap(&L->r[i], &L->r[i + 1]);
flag = 1;
}
}
if (flag == 0)
break;
}
}
//快速排序(分治递归)
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, j, min, max;
if (L->length == 0)
{
printf("需要排序的数据为空!");
return;
}
for (i = 1; i <= L->length - 1; i++)//排序的趟数L->length-1
{
min = i;
max = L->length - 1;
for (j = i; j <= max; j++)
{//比较第i个元素和其后的元素找到最小的和最大的
if (L->r[j] < L->r[min])
{
swap(&L->r[min], &L->r[j]);//交换两个数,每一趟将最小数放在前面
}
if (L->r[j] > L->r[max])
{
swap(&L->r[max], &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--)
{//将堆顶记录和当前未经排序的子序列L->r[1..i]中最后一个记录互换
swap(&L->r[1], &L->r[i]);
HeapAdjust(L, 1, i - 1); //将L->r[1..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*********** 7、归并排序 ***********\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~7)或退出系统(数字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 BININSERT:
start = clock();
CreateShow(&L);
BinInsert(&L);
end = clock();
PrintSeqList(&L);
printf("插入排序时间是:%f毫秒\n", (float)(end - start));
break;
case BUBBLE:
start = clock();
CreateShow(&L);
BubbleSort(&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;
}
各种排序算法的最差时间,时间复杂度及稳定性比较
排序算法 | 最差时间 | 时间复杂度 | 是否稳定 |
插入排序 | O(n2) | O(n2) | 稳定 |
冒泡排序 | O(n2) | O(n2) | 稳定 |
快速排序 | O(n2) | O(n*log2n) | 不稳定 |
选择排序 | O(n2) | O(n2) | 稳定 |
堆排序 | O(n*log2n) | O(n*log2n) | 不稳定 |
归并排序 | O(n*log2n) | O(n*log2n) | 稳定 |
本文出自 “Scen” 博客,请务必保留此出处http://10741357.blog.51cto.com/10731357/1730948