C/C++ 排序算法 及 时间复杂度和空间复杂度 (直接插入排序,折半插入排序,希尔排序,简单选择排序,堆排序,冒泡排序,快速排序,归并排序,基数排序)
2019-01-28 13:18
555 查看
一,直接插入排序
二,折半插入排序
三,希尔排序
四,简单选择排序
五,堆排序
六,冒泡排序
七,快速排序
八,归并排序
九,基数排序
一,插入排序
#include <stdio.h> // 分类 ------------- 内部比较排序 // 数据结构 ---------- 数组 // 最差时间复杂度 ---- 最坏情况为输入序列是降序排列的,此时时间复杂度O(n^2) // 最优时间复杂度 ---- 最好情况为输入序列是升序排列的,此时时间复杂度O(n) // 平均时间复杂度 ---- O(n^2) // 所需辅助空间 ------ O(1) // 稳定性 ------------ 稳定 void InsertionSort(int A[], int n) { for (int i = 1; i < n; i++) // 类似抓扑克牌排序 { int get = A[i]; // 右手抓到一张扑克牌 int j = i - 1; // 拿在左手上的牌总是排序好的 while (j >= 0 && A[j] > get) // 将抓到的牌与手牌从右向左进行比较 { A[j + 1] = A[j]; // 如果该手牌比抓到的牌大,就将其右移 j--; } A[j + 1] = get; // 直到该手牌比抓到的牌小(或二者相等),将抓到的牌插入到该手牌右边(相等元素的相对次序未变,所以插入排序是稳定的) } } int main() { int A[] = { 6, 5, 3, 1, 8, 7, 2, 4 };// 从小到大插入排序 int n = sizeof(A) / sizeof(int); InsertionSort(A, n); printf("插入排序结果:"); for (int i = 0; i < n; i++) { printf("%d ", A[i]); } printf("\n"); return 0; }
二,二分插入排序
#include <stdio.h> // 分类 -------------- 内部比较排序 // 数据结构 ---------- 数组 // 最差时间复杂度 ---- O(n^2) // 最优时间复杂度 ---- O(nlogn) // 平均时间复杂度 ---- O(n^2) // 所需辅助空间 ------ O(1) // 稳定性 ------------ 稳定 void InsertionSortDichotomy(int A[], int n) { for (int i = 1; i < n; i++) { int get = A[i]; // 右手抓到一张扑克牌 int left = 0; // 拿在左手上的牌总是排序好的,所以可以用二分法 int right = i - 1; // 手牌左右边界进行初始化 while (left <= right) // 采用二分法定位新牌的位置 { int mid = (left + right) / 2; if (A[mid] > get) right = mid - 1; else left = mid + 1; } for (int j = i - 1; j >= left; j--) // 将欲插入新牌位置右边的牌整体向右移动一个单位 { A[j + 1] = A[j]; } A[left] = get; // 将抓到的牌插入手牌 } } int main() { int A[] = { 5, 2, 9, 4, 7, 6, 1, 3, 8 };// 从小到大二分插入排序 int n = sizeof(A) / sizeof(int); InsertionSortDichotomy(A, n); printf("二分插入排序结果:"); for (int i = 0; i < n; i++) { printf("%d ", A[i]); } printf("\n"); return 0; }
五,堆排序
#include <stdio.h> // 分类 -------------- 内部比较排序 // 数据结构 ---------- 数组 // 最差时间复杂度 ---- O(nlogn) // 最优时间复杂度 ---- O(nlogn) // 平均时间复杂度 ---- O(nlogn) // 所需辅助空间 ------ O(1) // 稳定性 ------------ 不稳定 void Swap(int A[], int i, int j) { int temp = A[i]; A[i] = A[j]; A[j] = temp; } void Heapify(int A[], int i, int size) // 从A[i]向下进行堆调整 { int left_child = 2 * i + 1; // 左孩子索引 int right_child = 2 * i + 2; // 右孩子索引 int max = i; // 选出当前结点与其左右孩子三者之中的最大值 if (left_child < size && A[left_child] > A[max]) max = left_child; if (right_child < size && A[right_child] > A[max]) max = right_child; if (max != i) { Swap(A, i, max); // 把当前结点和它的最大(直接)子节点进行交换 Heapify(A, max, size); // 递归调用,继续从当前结点向下进行堆调整 } } int BuildHeap(int A[], int n) // 建堆,时间复杂度O(n) { int heap_size = n; for (int i = heap_size / 2 - 1; i >= 0; i--) // 从每一个非叶结点开始向下进行堆调整 Heapify(A, i, heap_size); return heap_size; } void HeapSort(int A[], int n) { int heap_size = BuildHeap(A, n); // 建立一个最大堆 while (heap_size > 1) // 堆(无序区)元素个数大于1,未完成排序 { // 将堆顶元素与堆的最后一个元素互换,并从堆中去掉最后一个元素 // 此处交换操作很有可能把后面元素的稳定性打乱,所以堆排序是不稳定的排序算法 Swap(A, 0, --heap_size); Heapify(A, 0, heap_size); // 从新的堆顶元素开始向下进行堆调整,时间复杂度O(logn) } } int main() { int A[] = { 5, 2, 9, 4, 7, 6, 1, 3, 8 };// 从小到大堆排序 int n = sizeof(A) / sizeof(int); HeapSort(A, n); printf("堆排序结果:"); for (int i = 0; i < n; i++) { printf("%d ", A[i]); } printf("\n"); return 0; }
六,冒泡排序
#include <stdio.h> // 分类 -------------- 内部比较排序 // 数据结构 ---------- 数组 // 最差时间复杂度 ---- O(n^2) // 最优时间复杂度 ---- 如果能在内部循环第一次运行时,使用一个旗标来表示有无需要交换的可能,可以把最优时间复杂度降低到O(n) // 平均时间复杂度 ---- O(n^2) // 所需辅助空间 ------ O(1) // 稳定性 ------------ 稳定 void Swap(int A[], int i, int j) { int temp = A[i]; A[i] = A[j]; A[j] = temp; } void BubbleSort(int A[], int n) { for (int j = 0; j < n - 1; j++) // 每次最大元素就像气泡一样"浮"到数组的最后 { for (int i = 0; i < n - 1 - j; i++) // 依次比较相邻的两个元素,使较大的那个向后移 { if (A[i] > A[i + 1]) // 如果条件改成A[i] >= A[i + 1],则变为不稳定的排序算法 { Swap(A, i, i + 1); } } } } int main() { int A[] = { 8,7,2,9,4,3,8,4,2,3 }; // 从小到大冒泡排序 int n = sizeof(A) / sizeof(int); BubbleSort(A, n); printf("冒泡排序结果:"); for (int i = 0; i < n; i++) { printf("%d ", A[i]); } printf("\n"); return 0; }
七,快速排序
#include <stdio.h> // 分类 ------------ 内部比较排序 // 数据结构 --------- 数组 // 最差时间复杂度 ---- 每次选取的基准都是最大(或最小)的元素,导致每次只划分出了一个分区,需要进行n-1次划分才能结束递归,时间复杂度为O(n^2) // 最优时间复杂度 ---- 每次选取的基准都是中位数,这样每次都均匀的划分出两个分区,只需要logn次划分就能结束递归,时间复杂度为O(nlogn) // 平均时间复杂度 ---- O(nlogn) // 所需辅助空间 ------ 主要是递归造成的栈空间的使用(用来保存left和right等局部变量),取决于递归树的深度,一般为O(logn),最差为O(n) // 稳定性 ---------- 不稳定 void Swap(int A[], int i, int j) { int temp = A[i]; A[i] = A[j]; A[j] = temp; } int Partition(int A[], int left, int right) // 划分函数 { int pivot = A[right]; // 这里每次都选择最后一个元素作为基准 int tail = left - 1; // tail为小于基准的子数组最后一个元素的索引 for (int i = left; i < right; i++) // 遍历基准以外的其他元素 { if (A[i] <= pivot) // 把小于等于基准的元素放到前一个子数组末尾 { Swap(A, ++tail, i); } } Swap(A, tail + 1, right); // 最后把基准放到前一个子数组的后边,剩下的子数组既是大于基准的子数组 // 该操作很有可能把后面元素的稳定性打乱,所以快速排序是不稳定的排序算法 return tail + 1; // 返回基准的索引 } void QuickSort(int A[], int left, int right) { if (left >= right) return; int pivot_index = Partition(A, left, right); // 基准的索引 QuickSort(A, left, pivot_index - 1); QuickSort(A, pivot_index + 1, right); } int main() { int A[] = { 5, 2, 9, 4, 7, 6, 1, 3, 8 }; // 从小到大快速排序 int n = sizeof(A) / sizeof(int); QuickSort(A, 0, n - 1); printf("快速排序结果:"); for (int i = 0; i < n; i++) { printf("%d ", A[i]); } printf("\n"); return 0; }
八,归并排序
#include <stdio.h> #include <limits.h> // 分类 -------------- 内部比较排序 // 数据结构 ---------- 数组 // 最差时间复杂度 ---- O(nlogn) // 最优时间复杂度 ---- O(nlogn) // 平均时间复杂度 ---- O(nlogn) // 所需辅助空间 ------ O(n) // 稳定性 ------------ 稳定 void Merge(int A[], int left, int mid, int right)// 合并两个已排好序的数组A[left...mid]和A[mid+1...right] { int len = right - left + 1; int *temp = new int[len]; // 辅助空间O(n) int index = 0; int i = left; // 前一数组的起始元素 int j = mid + 1; // 后一数组的起始元素 while (i <= mid && j <= right) { temp[index++] = A[i] <= A[j] ? A[i++] : A[j++]; // 带等号保证归并排序的稳定性 } while (i <= mid) { temp[index++] = A[i++]; } while (j <= right) { temp[index++] = A[j++]; } for (int k = 0; k < len; k++) { A[left++] = temp[k]; } } void MergeSortRecursion(int A[], int left, int right) // 递归实现的归并排序(自顶向下) { if (left == right) // 当待排序的序列长度为1时,递归开始回溯,进行merge操作 return; int mid = (left + right) / 2; MergeSortRecursion(A, left, mid); MergeSortRecursion(A, mid + 1, right); Merge(A, left, mid, right); } void MergeSortIteration(int A[], int len) // 非递归(迭代)实现的归并排序(自底向上) { int left, mid, right;// 子数组索引,前一个为A[left...mid],后一个子数组为A[mid+1...right] for (int i = 1; i < len; i *= 2) // 子数组的大小i初始为1,每轮翻倍 { left = 0; while (left + i < len) // 后一个子数组存在(需要归并) { mid = left + i - 1; right = mid + i < len ? mid + i : len - 1;// 后一个子数组大小可能不够 Merge(A, left, mid, right); left = right + 1; // 前一个子数组索引向后移动 } } } int main() { int A1[] = { 6, 5, 3, 1, 8, 7, 2, 4 }; // 从小到大归并排序 int A2[] = { 6, 5, 3, 1, 8, 7, 2, 4 }; int n1 = sizeof(A1) / sizeof(int); int n2 = sizeof(A2) / sizeof(int); MergeSortRecursion(A1, 0, n1 - 1); // 递归实现 MergeSortIteration(A2, n2); // 非递归实现 printf("递归实现的归并排序结果:"); for (int i = 0; i < n1; i++) { printf("%d ", A1[i]); } printf("\n"); printf("非递归实现的归并排序结果:"); for (int i = 0; i < n2; i++) { printf("%d ", A2[i]); } printf("\n"); return 0; }
下面是所有排序算法,可能会有错误。
#include<stdio.h> #include<stdlib.h> #include<string.h> //输出模块 void Output(int a[],int length) { for (int j = 0; j < length; j++) { printf("%d\t", a[j]); } printf("\n\n=============================\n\n"); } //一、直接插入排序(插入排序) //1、思想:最基本的插入排序,将第i个插入到前i - 1个中的适当位置。 //2、时间复杂度:O(n^2)。 //3、空间复杂度:O(1)。 //4、稳定性:稳定。 void InsSort(int a[],int length) { int temp = 0, j = 0, i = 0; for (i = 1; i <= length; i++) { temp = a[i]; //取出一个未排序的数据 for (j = i - 1; j >= 0 && temp < a[j]; j--) { a[j + 1] = a[j]; //向后移动数据 } a[j + 1] = temp; //插入数据到序列 } } //二、折半插入排序(插入排序) //1、思想:因为是已经确定了前部分是有序序列,所以在查找插入位置的时候可以用折半查找的方法进行查找,提高效率。 //2、时间复杂度:比较时的时间减为O(nlogn),但是移动元素的时间耗费未变,所以总是得时间复杂度还是O(n^2)。 //3、空间复杂度:S(n) = O(1)。 //4、稳定性:稳定。 void BinSort(int a[], int length) { int temp = 0, j = 0, i = 0; for (i = 1; i <= length; i++) { temp = a[i]; //待插入元素 int low = 0, high = i - 1; while (low <= high) { int m = (low + high) / 2; //折半 if (temp < a[m]) //插入点在低半区 { high = m - 1; } else //插入点在高半区 { low = m + 1; } } //向后移动数据 for (j = i - 1; j >= low; j--) { a[j + 1] = a[j]; } a[j + 1] = temp;//插入数据到序列 } } //三、希尔排序(插入排序) //1、思想:又称缩小增量排序法。把待排序序列分成若干较小的子序列,然后逐个使用直接插入排序法排序,最后再对一个较为有序的序列进行一次排序 // 主要是为了减少移动的次数,提高效率。原理应该就是从无序到渐渐有序,要比直接从无序到有序移动的次数会少一些。 //2、时间复杂度:O(n^1.5) //3、空间复杂度:O(1) //4、稳定性:不稳定。 {2, 4, 1, 2},2和1一组4和2一组,进行希尔排序,第一个2和最后一个2会发生位置上的变化。 void ShellInsert(int a[],int length) { int temp = 0, j = 0, i = 0; int step = length / 2; //取增量 //保证最后一个增量为1 while (step >= 1) { for (i = step; i < length; i++) { temp = a[i]; //每两个增量间隔的数据比较,将小数据向前移动 for (j = i - step; j >= 0 && temp < a[j]; j -= step) { a[j + step] = a[j]; } a[j + step] = temp; //保存数据 } step /= 2; //缩小增量 } } //四、简单选择排序(选择排序) //1、思想:每一趟排序将会选择出最小的(或者最大的)值,顺序放在已排好序的数列的后面 //2、时间复杂度:O(n^2) //3、空间复杂度:O(1) //4、稳定性:不稳定 void SelectionSort(int a[], int length) { int temp = 0, j = 0, i = 0; for (i = 0; i < length; i++) { for (j = i + 1; j < length; j++) { //前一个数大于后一个数,交换 if (a[i] > a[j]) { temp = a[j]; a[j] = a[i]; a[i] = temp; } } } } //五、堆排序(选择排序) //1、思想:堆排序利用这种堆这种数据结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素 //2、时间复杂度:O(nlogn)。 //3、空间复杂度:O(1)。 //4、稳定性:不稳定。 void heapAdjust(int a[], int parent, int length) { int temp = a[parent]; // temp保存当前父节点 int child = 2 * parent + 1;// 先获得左孩子 while (child < length) { // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点 if (child + 1 < length && a[child] < a[child + 1]) { child++; } // 如果父结点的值已经大于孩子结点的值,则直接结束 if (temp >= a[child]) break; // 把孩子结点的值赋给父结点 a[parent] = a[child]; // 选取孩子结点的左孩子结点,继续向下筛选 parent = child; child = 2 * child + 1; } a[parent] = temp; } void HeadSort(int a[], int length) { int i; // 循环建立初始堆 // 从 0 到 length/2 ,这些都是有孩子的节点 // 没孩子的节点构造大顶堆就无意义了 for (i = length / 2; i >= 0; i--) { heapAdjust(a, i, length); } // 进行n-1次循环,完成排序 for (i = length; i > 0; i--) { int temp = a[0]; a[0] = a[i]; a[i] = temp; // 筛选 a[0] 结点,得到i-1个结点的堆 heapAdjust(a, 0, i); } } //六、冒泡排序(交换排序) //1、思想:将序列当中的左右元素,依次比较,保证左边的元素始终小于右边的元素。 //2、时间复杂度:O(n^2) //3、空间复杂度:O(1) //4、稳定性:稳定 void Swap(int A[], int i, int j) { int temp = A[i]; A[i] = A[j]; A[j] = temp; } void BubbleSort(int A[], int n) { for (int j = 0; j < n - 1 ; j++) // 每次最大元素就像气泡一样"浮"到数组的最后 { for (int i = 0; i < n - 1 - j; i++) // 依次比较相邻的两个元素,使较大的那个向后移 { if (A[i] > A[i + 1]) // 如果条件改成A[i] >= A[i + 1],则变为不稳定的排序算法 { Swap(A, i, i + 1); } } } } //七、快速排序 //思想:通过一趟排序将待排记录分割成两个部分,其中一部分记录关键字均比另一部分记录的关键字小,则可以分别对这两部分关键字继续排序,以达到整个序列有序的目的。 //时间复杂度:O(nlogn), 最坏的情况下为O(n^2) //空间复杂度:O(1) //稳定性:不稳定 //本质就是, 找一个基位(枢轴, 分水岭, 作用是左边的都比它小, 右边的都比它大.可随机, 取名base //首先从序列最右边开始找比base小的 //如果小, 换位置, 从而base移到刚才右边(比较时比base小)的位置(记为临时的high位), 这样base右边的都比base大 //然后, 从序列的最左边开始找比base大的 //如果大, 换位置, 从而base移动到刚才左边(比较时比base大)的位置(记为临时的low位), 这样base左边的都比base小 //循环以上两步, 直到 low == high, 这使才真正的找到了枢轴, 分水岭.返回这个位置, 分水岭左边和右边的序列, 分别再来递归 // 分水岭,基位,左边的都比这个位置小,右边的都大 int partition(int a[], int low, int high) { int base = a[low]; //用子表的第一个记录做枢轴(分水岭)记录 while (low < high) { //更改下面两个while循环中的<=和>=,即可获取到从大到小排列 //从表的两端交替向中间扫描,从小到大排列 while (low < high && a[high] >= base)high--; //如果高位小于base,base赋值给当前high位,base挪到(互换)到了这里,high位右边的都比base大 int temp = a[high]; a[high] = a[low]; a[low] = temp; while (low < high && a[low] <= base)low++; //如果低位大于base temp = a[high]; a[high] = a[low]; a[low] = temp; } //现在low=heigh return low; } void QuickSort(int a[], int low, int high) { if (low < high) { int division = partition(a, low, high); QuickSort(a, low, division - 1); QuickSort(a, division + 1, high); } } //八、归并排序 //思想:归并排序是将两个或两个以上的有序表组合成一个有序表,该算法是采用分治法实现 //时间复杂度:O(nlogn) //空间复杂度:O(n) //稳定性:稳定 //归并排序其实要做两件事: //(1)“分解”——将序列每次折半划分。 //(2)“合并”——将划分后的序列段两两合并后排序。 void Merge(int a[], int low, int mid, int high)//合并 { int i = low; // i是第一段序列的下标 int j = mid + 1; // j是第二段序列的下标 int k = 0; // k是临时存放合并序列的下标 int a2[100]; // 扫描第一段和第二段序列,直到有一个扫描结束 while (i <= mid && j <= high) { // 判断第一段和第二段取出的数哪个更小,将其存入合并序列,并继续向下扫描 if (a[i] <= a[j]) { a2[k] = a[i]; i++; k++; } else { a2[k] = a[j]; j++; k++; } } // 若第一段序列还没扫描完,将其全部复制到合并序列 while (i <= mid) { a2[k] = a[i]; i++; k++; } // 若第二段序列还没扫描完,将其全部复制到合并序列 while (j <= high) { a2[k] = a[j]; j++; k++; } // 将合并序列复制到原始序列中 for (k = 0, i = low; i <= high; i++, k++) { a[i] = a2[k]; } } void MergePass(int a[], int gap, int length)//分解 { int i = 0; // 归并gap长度的两个相邻子表 for (i = 0; i + 2 * gap - 1 <= length; i = i + 2 * gap) { Merge(a, i, i + gap - 1, i + 2 * gap - 1); } // 余下两个子表,后者长度小于gap if (i + gap - 1 <= length) { Merge(a, i, i + gap - 1, length); } } void MergeSort(int a[],int length) { for (int gap = 1; gap <= length; gap = 2 * gap) { MergePass(a, gap, length); } } //九、基数排序 //思想:基数是按照低位先排序,然后收集;再按高位排序,然后再收集,依次类推,直到最高位。 //注:表示关键词分类到radix(基数)个盒子,在关键词为数字时,基数为10,当关键词为字母时,基数为26 //时间复杂度:O(n + d) //空间复杂度:O(n) //稳定性:稳定 //================================ //=============主函数============= //================================ //选择界面 int main() { // a 存储整数的数组,最大100位 // i 计数器,记载a的长度 // p 指向a数组首地址的指针 //输入 int a[100], i; int *p = a; printf("请输入要排序的数(以空格隔开,以回车结束):"); for (i = 0;; i++) { scanf("%d", &a[i]); if (getchar() == '\n')break; } i+=1; //测试输出 printf("\n=============================\n\n"); printf("输入的数组为:\n"); Output(p, i); printf("请选择排序算法(输入其他字符退出):\n"); printf("1、直接插入排序\n"); //插入排序 printf("2、折半插入排序\n"); //插入排序 printf("3、希尔排序\n"); //插入排序 printf("4、简单选择排序\n"); //选择排序 printf("5、堆排序\n"); //选择排序 printf("6、冒泡排序\n"); //交换排序 printf("7、快速排序\n"); //交换排序 printf("8、归并排序\n"); //printf("9、基数排序\n"); int choose = 0; scanf("%d", &choose); switch (choose) { case 1:InsSort(p, i); break; case 2:BinSort(p, i); break; case 3:ShellInsert(p, i); break; case 4:SelectionSort(p, i); break; case 5:HeadSort(p, i); break; case 6:BubbleSort(p, i); break; case 7:QuickSort(p, 0, i); break; case 8:MergeSort(p, i); break; //case 9: break; default:exit(0); break;//输入其他数字退出 } printf("\n=============================\n\n"); printf("排序后数组为:\n"); Output(p, i);//输出排序后的数组 system("pause"); }
相关文章推荐
- 排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序...
- 排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序
- 排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序
- C++实现直接插入排序,折半插入排序,希尔排序,冒泡排序,简单选择排序,快速排序,堆排序
- C++排序:冒泡排序,简单选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序
- C++实现常用排序算法(快速排序、冒泡排序、希尔排序、折半插入排序、直接插入排序)
- 数据结构——内部排序算法比较(冒泡排序、直接插入排序、简单选择排序、希尔排序、快速排序、堆排序、归并排序)
- 牛客网Java刷题知识点之插入排序(直接插入排序和希尔排序)、选择排序(直接选择排序和堆排序)、冒泡排序、快速排序、归并排序和基数排序(博主推荐)
- 排序算法合集(插入排序,折半插入排序,希尔排序,冒泡排序,快速排序,简单选择排序,堆排序,归并排序)
- 6种排序算法及其比较 简单选择排序,堆排序,简单插入排序,希尔排序,冒泡排序,快速排序,归并排序
- 程序员必知的8大排序(①直接插入排序②希尔排序③简单选择排序④堆排序⑤冒泡排序⑥快速排序⑦归并排序⑧基数排序)
- 排序算法: 冒泡排序, 快速排序,希尔排序,直接插入排序 ,直接选择排序,归并排序,堆排序
- python排序算法-冒泡排序,选择排序,直接插入排序,希尔排序,归并排序,快速排序,堆排序
- 冒泡排序 快速排序 选择排序 堆排序 直接插入排序 希尔排序 归并排序
- 直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序及归并排序
- 几种常见的排序算法,选择排序,冒泡排序,希尔排序,堆排序,快速排序,归并排序,基数排序的比较
- 插入排序、冒泡排序、选择排序、希尔排序、快速排序、归并排序、堆排序和LST基数排序的C++代码实现
- c++: 直接插入排序,冒泡排序,快速排序,堆排序和归并排序
- 排序算法汇总(选择排序 ,直接插入排序,冒泡排序,希尔排序,快速排序,堆排序)
- 初级版、正宗版、升级版冒泡排序;简单选择排序;直接插入排序;希尔排序;堆排序;递归法 、非递归法归并排序;快速排序; 快速排序优化算法