数据结构之常用的内部排序算法
一,目的
-
掌握顺序表和单链表的存储特点及插入、删除等算法。
-
灵活运用顺序表和单链表的相关算法实现一元多项式的计算。
二,描述
通过一个简单的菜单,分别实现下列排序要求,采用几组不同数据测试各排序算法的性能(比较次数和移动次数)及稳定性。
实现简单选择排序、直接插入排序和冒泡排序;
实现折半插入排序;
实现希尔排序算法;
实现快速排序算法(递归和非递归);
实现堆排序算法。
(1)输入:
根据菜单提示选择排序算法,输入一组待排序数据。
(2)输出:
输出排序结果(体现排序过程),及排序过程中数据的比较次数和移动
三,代码测试
- 方案
测试数据 | |
---|---|
直接插入排序 | 50 23 6 71 90 33 99 45 |
折半插入排序 | 33 99 45 4 99 2 50 13 |
希尔排序 | 6 71 50 66 12 9 67 43 |
简单选择排序 | 3 99 45 23 60 47 91 7 |
冒泡排序 | 6 71 51 88 19 45 37 51 |
快速排序 | 50 23 6 55 60 57 91 66 |
堆排序 | 5 33 73 91 20 87 93 91 |
- 结果
1,直接插入排序
2,折半插入排序
3,希尔排序
4,简单选择排序
5,冒泡排序
6,快速排序
7,堆排序
四,部分源码
-
主要数据类型与变量
typedef int KeyType; typedef struct{ KeyType key; //关键字类型 }RedType; //顺序表类型 typedef struct{ RedType *r; //r[0]闲置或用作哨兵单元 int length; //顺序表长度 }SqList;
-
部分函数模块
void InserSort(SqList &L){ //直接插入排序 int i, j, m, n; m = n = 0; for(i = 2; i <= L.length; i++){ if(LT(L.r[i].key, L.r[i-1].key)){ L.r[0] = L.r[i]; L.r[i] = L.r[i-1]; n+=2; m++; for(j=i-2; LT(L.r[0].key, L.r[j].key); --j){ L.r[j+1] = L.r[j]; m++; n++; } L.r[j+1] = L.r[0]; PrintList_Sq(L); } m++; } printf("比较次数为:%d\n", m); printf("移动次数为:%d\n", n); } void BInsertSort(SqList &L){ //折半插入排序 int m, i, j, a, b; a = b =0; for(i=2; i<=L.length; ++i){ L.r[0] = L.r[i]; b++; int low = 1; int high = i - 1; while(low <= high){ m = (low + high)/2; if(LT(L.r[0].key, L.r[m].key)) high = m-1; else low = m + 1; a++; } for(j=i-1; j>=high+1; --j){ L.r[j+1] = L.r[j]; b++; } L.r[high+1] = L.r[0]; b++; PrintList_Sq(L); } a++; printf("比较次数为:%d\n", a); printf("移动次数为:%d\n", b); } void ShellInsert(SqList &L, int dk, SqList &H){ //希尔排序 增量 int i, j, m, n; m = n =0; for(i=dk+1; i<=L.length; ++i) if(LT(L.r[i].key, L.r[i-dk].key)){ L.r[0] = L.r[i]; n++; for(j=i-dk; j>0 && LT(L.r[0].key, L.r[j].key); j-=dk){ L.r[j+dk] = L.r[j]; m++; n++; } L.r[j+dk] = L.r[0]; n++; m++; } PrintList_Sq(L); H.length += m; H.r[0].key += n; } void ShellSort(SqList &L){ //希尔排序 SqList H; InitList(H, 1); H.length = 0; H.r[0].key = 0; int a = L.length; int b = a/2; while(b>=1){ ShellInsert(L, b, H); b = b/2; } printf("比较次数为:%d\n", H.length); printf("移动次数为:%d\n", H.r[0].key); } Status SelectMinKey(SqList L, int i){ //在L.r[i..L.length]中选择key最小的 int min = i; int a = L.r[min].key; for(i; i<L.length; i++){ if(L.r[i+1].key < a){ min = i+1; a = L.r[i+1].key; } } i = min; return i; } void SelectSort(SqList &L){ //简单选择排序 int i, j, m; m = L.length; for(i=1; i<L.length; ++i){ j = SelectMinKey(L, i); if(i!=j){ L.r[0] = L.r[i]; L.r[i] = L.r[j]; L.r[j] = L.r[0]; } PrintList_Sq(L); } printf("比较次数为:%d\n", m*(m-1)/2); printf("移动次数为:%d\n", m-1); } void bubbleSort(SqList &L){ //冒泡排序 int i, j, m, n; m = n =0; for(i=1; i<L.length; i++){ for(j=1; j<L.length-i+1; j++){ if(L.r[j].key > L.r[j+1].key) { L.r[0] = L.r[j]; L.r[j] = L.r[j+1]; L.r[j+1] = L.r[0]; n += 2; } m++; } PrintList_Sq(L); printf("比较次数为:%d\n", m); printf("移动次数为:%d\n", n); } } void QSort(SqList &L, int low, int high, SqList &H){ //快速排序 int pivotloc; if(low < high){ pivotloc = Partition(L, low, high, H); QSort(L, low, pivotloc-1, H); QSort(L, pivotloc+1, high, H); } } Status Partition(SqList &L, int low, int high, SqList &H){ //快速排序中轴 int m, n; m = n = 0; L.r[0] = L.r[low]; n++; int pivotkey = L.r[low].key; while(low < high){ while(low<high && L.r[high].key>=pivotkey){ --high; m++; } L.r[low] = L.r[high]; n++; while(low<high && L.r[low].key<=pivotkey){ ++low; m++; } L.r[high] = L.r[low]; n++; } L.r[low] = L.r[0]; n++; PrintList_Sq(L); H.length +=m; H.r[0].key +=n; return low; } void HeapAdjust(SqList &H, int s, int m, SqList &L){ //建堆 int j; int a, b; a = b = 0; RedType rc; rc = H.r[s]; b++; for(j=2*s; j<=m; j*=2){ if(j<m && LT(H.r[j].key, H.r[j+1].key) ){ ++j; a++; } if(!LT(rc.key, H.r[j].key)){ break; a++; } a++; H.r[s] = H.r[j]; s = j; b++; } H.r[s] = rc; b++; L.length += a; L.r[0].key += b; } void HeapSort(SqList &H){ //堆排序 int i; SqList L; InitList(L, 1); L.length = 0; L.r[0].key = 0; for(i=H.length/2; i>0; --i) HeapAdjust(H, i, H.length, L); for(i = H.length; i>1; --i){ H.r[0] = H.r[1]; H.r[1] = H.r[i]; H.r[i] = H.r[0]; L.r[0].key +=2; PrintList_Sq(H); HeapAdjust(H, 1, i-1, L); } printf("比较次数为:%d\n", H.length); printf("移动次数为:%d\n", H.r[0].key); }