一、实验目的
1.掌握常见的内部排序算法的思想及其适用条件; 2.掌握常见的内部排序算法的程序实现;
二、实验内容及要求
1、任务描述 设计一个内部排序算法模拟系统,利用该系统实现常用的 7 种排序算法,并测试 各种排序算法的性能。 ?实验内容:通过一个简单的菜单,分别实现下列排序要求,采用几组不同数据测试各排 序算法的性能(比较次数和移动次数)及稳定性。 ◆ 实现简单选择排序、直接插入排序和冒泡排序; ◆ 实现折半插入排序; ◆ 实现希尔排序算法; ◆ 实现快速排序算法(递归和非递归); ◆ 实现堆排序算法 ?输入和输出: (1)输入形式:根据菜单提示选择排序算法,输入一组带排序数据。 (2)输出形式:输出排序结果(体现排序过程),及排序过程中数据的比较次数和移动次数,判断排序算法的稳定性。 ?实验要求: ?实现一个简单的交互式界面,包括系统菜单、清晰的输入提示等。 ◆ 要输出每一趟排序的结果。 ◆ 能够上机编辑、调试出完整的程序。 2、主要数据类型与变量
typedef struct
{
int r[MAXSIZE + 1];
int length;
}SqList;
#define MAXSIZE 10000
3、算法或程序模块
1. void SelectSort(SqList* L)
通过n-1次关键词间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i个记录进行交换。
2.void InsertSort(SqList* L)
将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录数增1的有序表。
3.void BubbleSort(SqList* L)
两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。
4.void BinarySort(SqList* L)
不断的依次将元素插入前面已排好序的序列中。由于前半部分为已排好序的数列,因此不用按顺序依次寻找插入点,可以采用折半查找的方法来加快寻找插入点的速度。
5. void ShellSort(SqList* L)
将相距某个增量的记录组成一个子序列,保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。
6. void QSort(SqList* L, int low, int high)
通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到对整个序列有序的目的。
7. void QSort(SqList* L, int low, int high)
将待排序的序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根结点。将它移走,然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值。
三、测试
1、方案
2.结果
1选择排序:
2.直接插入排序:
3.冒泡排序:
4.折半插入排序:
5.希尔排序:
6.快速排序:
7.堆排序:
测试结果都正确,程序设计无误。
四、总结与讨论
此实验主要应用于对六种内部排序算法移动和比较次数的比较。通过对冒泡排序、直接插入插排序、简单选择排序、折半插入排序、快速排序、希尔排序、堆排序这几种内部排序算法进行比较,加深了我对这些排序的基本思想及排序算法的掌握和理解。同时通过该题目的设计过程,我也加深理解各种数据结构的逻辑结构、存储结构及相应上运算的实现,进一步理解和熟练掌握课本中所学的各种数据结构,进一步提升了自身的动手能力。 在之前的编程应用中我经常用的是选择法排序,第一个for循环用来控制选择的轮数,第二个for循环用来不断地选择最小或最大的值来放入指定的位置,实现也很方便。同时也掌握了冒泡法排序的思想和具体的代码实现过程,因为平常编写的程序排序的数据都比较少,因此也不太能明显地感受到时间复杂度的不同对于程序的影响,但经过本章排序算法的学习后,我了解到虽然冒泡法排序和选择法排序的时间复杂度都是O(n2),但是选择法排序的性能要稍微优于冒泡法排序。 同时我也了解了三种时间复杂度更为优越的算法,分别是希尔排序、堆排序和快速排序,它们都将时间复杂度提升到了O(nlogn),对于前两个我大致了解了其排序的思路,认识到希尔排序相当于直接插入排序的升级,堆排序相当于简单选择排序的升级,但对于快速排序我了解到它被列为20世纪十大算法之一,因此我仔细熟悉了其算法的具体实现过程,尤其是利用Partition函数去获得枢轴所在的位置的思想确实让我收获很大,感受到了这种算法的便利。因此今后在面对较多数据的排序时,我会再进一步熟悉并利用这种排序算法,以实现程序更加高效的执行。
附:程序的源代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAX_LENGTH_INSERT_SORT 7
typedef int Status;
#define MAXSIZE 10000
typedef struct
{
int r[MAXSIZE + 1];
int length;
}SqList;
void swap(SqList* L, int i, int j)
{
int temp = L->r[i];
L->r[i] = L->r[j];
L->r[j] = temp;
}
void print(SqList L)
{
int i;
for (i = 1; i < L.length; i++)
printf("%d,", L.r[i]);
printf("%d", L.r[i]);
printf("\n");
}
void BubbleSort(SqList* L)
{
int i, j,k=0;
for (i = 1; i < L->length; i++)
{
for (j = L->length - 1; j >= i; j--)
{
if (L->r[j] > L->r[j + 1])
{
swap(L, j, j + 1);
printf(" 第%d趟排序结果: ", ++k);
print(*L);
}
}
}
}
void SelectSort(SqList* L)
{
int i, j,k=0;
for (i = 1; i < L->length; i++)
{
for (j = i + 1; j <= L->length; j++)
{
if (L->r[i] > L->r[j])
{
swap(L, i, j);
printf(" 第%d趟排序结果: ", ++k);
print(*L);
}
}
}
}
void InsertSort(SqList* L)
{
int i, j,k=0;
for (i = 2; i <= L->length; i++)
{
if (L->r[i] < L->r[i - 1])
{
L->r[0] = L->r[i];
for (j = i - 1; L->r[j] > L->r[0]; j--)
L->r[j + 1] = L->r[j];
L->r[j + 1] = L->r[0];
printf(" 第%d趟排序结果: ", ++k);
print(*L);
}
}
}
void BinarySort(SqList* L)
{
int i, j, low = 0, high = 0, mid,k=0;
int temp = 0;
for (i = 2; i < L->length+1; i++) {
low = 1;
high = i-1;
temp = L->r[i];
while (low <= high) {
mid = (low + high) / 2;
if (L->r[mid] > temp) {
high = mid - 1;
}
else {
low = mid + 1;
}
}
for (j = i; j > low; j--) {
L->r[j] = L->r[j - 1];
printf(" 第%d趟排序结果: ", ++k);
print(*L);
}
L->r[low] = temp;
}
}
void ShellSort(SqList* L)
{
int i, j, k = 0;
int increment = L->length;
do
{
increment = increment / 3 + 1;
for (i = increment + 1; i <= L->length; i++)
{
if (L->r[i] < L->r[i - increment])
{
L->r[0] = L->r[i];
for (j = i - increment; j > 0 && L->r[0] < L->r[j]; j -= increment)
L->r[j + increment] = L->r[j];
L->r[j + increment] = L->r[0];
}
}
printf(" 第%d趟排序结果: ", ++k);
print(*L);
} while (increment > 1);
}
void HeapAdjust(SqList* L, int s, int m)
{
int temp, j;
temp = L->r[s];
for (j = 2 * s; j <= m; j *= 2)
{
if (j < m&& L->r[j] < L->r[j + 1])
++j;
if (temp >= L->r[j])
break;
L->r[s] = L->r[j];
s = j;
}
L->r[s] = temp;
}
void HeapSort(SqList* L)
{
int i,k=0;
for (i = L->length / 2; i > 0; i--)
HeapAdjust(L, i, L->length);
for (i = L->length; i > 1; i--)
{
swap(L, 1, i);
HeapAdjust(L, 1, i - 1);
printf(" 第%d趟排序结果: ", ++k);
print(*L);
}
}
int Partition(SqList* L, int low, int high)
{
int pivotkey;
pivotkey = L->r[low];
while (low < high)
{
while (low < high && L->r[high] >= pivotkey)
high--;
swap(L, low, high);
while (low < high && L->r[low] <= pivotkey)
low++;
swap(L, low, high);
}
return low;
}
int t = 0;
void QSort(SqList* L, int low, int high)
{
int pivot;
if (low < high)
{
pivot = Partition(L, low, high);
QSort(L, low, pivot - 1);
QSort(L, pivot + 1, high);
}
printf(" 第%d趟排序结果: ", ++t);
print(*L);
}
void QuickSort(SqList* L)
{
QSort(L, 1, L->length);
t = 0;
}
#define N 9
int main()
{
int i, n;
int d[MAXSIZE];
printf("请输入待排序元素的个数:\n");
scanf("%d", &n);
printf("请依次输入元素:\n");
SqList sq1,sq2,sq3,sq4,sq5,sq6,sq7,sq8;
for (i = 0; i < n; i++)
{
scanf("%d", &sq1.r[i + 1]);
}
sq1.length = n;
sq2=sq3=sq4=sq5=sq6=sq7=sq8 = sq1;
printf("排序前:\n");
print(sq1);
while (1)
{
int flag;
printf("---------------操作命令集---------------\n");
printf("****************************************\n");
printf("* 1.选择排序 *\n");
printf("* 2.直接插入排序 *\n");
printf("* 3.冒泡排序 *\n");
printf("* 4.折半插入排序 *\n");
printf("* 5.希尔排序 *\n");
printf("* 6.快速排序 *\n");
printf("* 7.堆排序 *\n");
printf("* 0.Return *\n");
printf("****************************************\n");
scanf("%d", &flag);
switch (flag)
{
case 1:
printf("选择排序:\n");
SelectSort(&sq2);
print(sq2);
break;
case 2:
printf("直接插入排序:\n");
InsertSort(&sq3);
print(sq3);
break;
case 3:
printf("冒泡排序:\n");
BubbleSort(&sq4);
print(sq4);
break;
case 4:
printf("折半插入排序:\n");
BinarySort(&sq5);
print(sq5);
break;
case 5:
printf("希尔排序:\n");
ShellSort(&sq6);
print(sq6);
break;
case 6:
printf("快速排序:\n");
QuickSort(&sq7);
print(sq7);
break;
case 7:
printf("堆排序:\n");
HeapSort(&sq8);
print(sq8);
break;
default:
break;
}
}
return 0;
}
|