排序算法
#include <iostream> #define MAXSIZE 10 typedef struct { int r[MAXSIZE + 1];//用于存储排序的数组,r[0]用作哨兵或临时变量 int length; //用于记录顺序表的长度 }SqlList; void swap(SqlList* L, int i, int j) { int temp = L->r[i]; L->r[i] = L->r[j]; L->r[j] = temp; } /* 基本思想:从头开始将每个元素与后面的每个元素比较,将较小的放在当前位置,这样下来就将最小的元素放在了当前位置 但前面排好的对后面的没有作用,也许较小的放到后面了 */ void BubbleSort0(SqlList* L) { int i, j; 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); //交换i和j对应元素的值 } } } } //从后往前比较 void BubbleSort(SqlList* L) { int i, j; 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); } } } } //从前往后比较 void BubbleSort1(SqlList* L) { int i, j; bool bFalg = true;//如果一次比较没变动直接退出循环,提高效率 for (i = 1; i < L->length && bFalg; ++i) { bFalg = false; for (j = 1; j <= L->length - i; ++j) { if (L->r[j] > L->r[j + 1]) { swap(L, j, j + 1); bFalg = true; } } } } /* 选择排序,从前往后记录最小位置,然后找出后面最小的然后和当前位置交换,这个是比较次数较多,外层for只进行一次比较 */ void SelectSort(SqlList* L) { int i, j, min; for (i = 1; i < L->length; ++i) { min = i; for (j = i + 1; j <= L->length; ++j) { if (L->r[min] > L->r[j]) { min = j; } } } if (i != min) { swap(L, i, min); } } /* 基本思想:先假定前面排好序,然后将要排序的插入到前面有序的数组中 o(n2)性能比冒泡和简单选择排序性能要好 */ void InsertSort(SqlList* L) { for (int i = 2; i < L->length; ++i) { L->r[0] = L->r[i];//当前元素存储在哨兵中 int j; for (j = i - 1; j >= 1; --j) { if (L->r[j] > L->r[0]) { L->r[j + 1] = L->r[j]; } else { break; } } L->r[j + 1] = L->r[0]; } } int Partition(SqlList* L, int low, int high) { int val = L->r[low];// 存放要分割的值 while (low < high && L->r[high] > L->r[low])//先进行high移动,只要比分割值大就左移 high--; swap(L, low, high);//对应的值小于分割值,则进行替换l对应值 while (low < high && L->r[low] < L->r[high])//进行low移动,比分割之小右移 low++; swap(L, low, high);//如果大于分割值替换h对应值 return low; } void QSort(SqlList* 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); } } /* 先选择轴值,左右指针,如果右边的索引比轴值小往做移动,然后比较左边,如果左边的索引比轴值大往右移动,当左索引和右索引相等时该位置就是轴值呆的地方 然后再比较轴值左边的,在比较轴值右边的 通过一趟将待排序的记录,将记录分割成两部分,一部分比另一部分小,接下来再进行左右两部分记录的排序 */ void QuickSort(SqlList* L) { QSort(L, 1, L->length); } /* 基本思想:每次按照跨度排序,然后这个跨度不断的减小,每次排序内部是插入排序 插入排序对于基本有序和较短的序列有较高的效率,时间复杂度为n1.5次方 并且这个跨度有限制的,例如除以二递减还是n2方的 */ void ShellSort(SqlList* L) { int i, j; 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]; } } } while (increment > 1); } void MSort(int SR[], int TR1[], int s, int t) { int m; int TR2[MAXSIZE + 1]; if (s == t) { TR1[s] = SR[s]; } else { s = (s + t) / 2; MSort(SR, TR2, s, m); MSort(SR, TR2, m + 1, t); //Merge(TR2, TR1, s, m, t);未实现看大话 } } /* 看这个归并排序很复杂,程序更是复杂,能写出来的也是牛B 3 4 21 45 52 134 4 67 45 34 3 4 21 45 52 134 4 67 45 34 3 4 21 45 52 134 4 67 45 34 3 4 21 45 52 134 4 67 45 34 3 4 21 45 52 4 134 34 45 67 3 4 21 45 52 4 34 45 67 134 3 4 4 21 34 45 45 52 67 134 其大体思想就是先进行对半分割,然后再两两合并排序一直到所有的都排序了 */ void MergeSort(SqlList* L) { MSort(L->r, L->r, 1, L->length); } /* 堆排序(理解思路就行了,写就算了) 先将待排序的数字建成最小值堆,建立最小值堆的速度还是挺快的 堆:分为大根堆和小根堆,属于完全二叉树(完全二叉树可以用数组存储) 加入要从小排序,就每次从根节点取,最从小排序了 */ /* 优先队列:好像是二叉树实现的 散列表(哈希表):用哈希函数计算存储数据的地址 */ int main() { SqlList qList; int num[MAXSIZE] = {9, 1, 5, 8, 3, 7, 4, 6, 2, 10}; memcpy(&qList.r[1], &num[0], MAXSIZE * sizeof(int)); qList.length = MAXSIZE; //BubbleSort0(&qList); //BubbleSort(&qList); //BubbleSort1(&qList); //InsertSort(&qList); //QuickSort(&qList); ShellSort(&qList); for (auto j : qList.r) { std::cout << j << " "; } getchar(); return 0; }