数据结构6-排序算法(直接插入排序、希尔排序、快速排序、归并排序和堆排序)
2017-10-07 13:46
691 查看
所有排序中,需要排序的数组array的第0位不存放有效的数字,而是作为哨兵存在。
1.直接插入排序
直接插入排序的基本操作是将一个记录插入到已排好序的表中,从而得到一个新的、记录增1的有序表。一个无序的数字array(同时可以把它当做一个长度为1的有序表),从1以后的每个位置都希望找到自己合适的位置插入,第i位(i从2开始)数字要到自己位置插入,那么就需要从前i-1位开始依次比较(比前一位大,比后一位小),同时后移记录。直到有序表的长度为数组array的长度。
2.希尔排序
希尔排序是直接插入排序的一个改良版。它的思想是:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列“基本有序”时,再对全体记录进行一次直接插入排序。
3.快速排序
快速排序是冒泡排序的一种改进版。它的基本思想是,通过一趟排序将带排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,已达到整个序列有序。
4.归并排序
归并排序的思想是,把初始的序列表的每一个关键字都视为一个序列表,然后将相邻两序列表合并成一个序列表并排序,多次合并后最终达到只剩一个表。
归并排序是一种非常稳定的排序,在多数情况下排序时间都可以稳定到一个小的范围内。时间复杂度O(nlogn)。
5.堆排序
当序列满足Ki >= K(2i) && Ki >= K(2i+1)时,这个序列就是大顶堆,简单的说就是制造出一个二叉树,其根节点大于两子节点。堆排序就需要制造出这些大顶堆,则堆顶的就是最大的数,我们把堆顶移到序列末尾,再重新制造大顶堆,重复之前的步骤。
1.直接插入排序
直接插入排序的基本操作是将一个记录插入到已排好序的表中,从而得到一个新的、记录增1的有序表。一个无序的数字array(同时可以把它当做一个长度为1的有序表),从1以后的每个位置都希望找到自己合适的位置插入,第i位(i从2开始)数字要到自己位置插入,那么就需要从前i-1位开始依次比较(比前一位大,比后一位小),同时后移记录。直到有序表的长度为数组array的长度。
/// <summary> /// 插入排序 /// </summary> public void InsertSort(int[] array) { int i = 0, j = 0; for (i = 2; i < array.Length; i++) { if (array[i] < array[i - 1]) { array[0] = array[i]; array[i] = array[i - 1]; for (j = i - 2; array[0] < array[j]; j--) { array[j + 1] = array[j]; } array[j + 1] = array[0]; } } }直接插入排序适合给本来就较为有序的数组做排序,因为数组越有序,插入的次数就越少。时间复杂度为O(n^2)。
2.希尔排序
希尔排序是直接插入排序的一个改良版。它的思想是:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列“基本有序”时,再对全体记录进行一次直接插入排序。
/// <summary> /// 希尔排序 /// </summary> /// <param name="array"></param> public void ShellSort(int[] array) { int[] dlta = new[] {5, 3, 1}; for (int i = 0; i < dlta.Length; i++) { ShellInsert(array, dlta[i]); } } private void ShellInsert(int[] array, int dk) { int i = 0, j = 0; for (i = dk + 1; i < array.Length; i++) { if (array[i] < array[i - dk]) { array[0] = array[i]; for (j = i - dk; j > 0 && array[0] < array[j]; j -= dk) { array[j + dk] = array[j]; } array[j + dk] = array[0]; } } }
3.快速排序
快速排序是冒泡排序的一种改进版。它的基本思想是,通过一趟排序将带排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,已达到整个序列有序。
/// <summary> /// 快速排序 /// </summary> /// <param name="array"></param> public void QuickSort(int[] array) { QSort(array, 1, array.Length - 1); } private void QSort(int[] array, int low, int high) { if (low < high) { int pivokey = Partition(array, low, high); QSort(array, low, pivokey - 1); QSort(array, pivokey + 1, high); } } private int Partition(int[] array, int low, int high) { array[0] = array[low]; int pivokey = array[low]; while (low < high) { while (low < high && array[high] >= pivokey) high--; array[low] = array[high]; while (low < high && array[low] <= pivokey) low++; array[high] = array[low]; } array[low] = pivokey; return low; }快速排序适合比较“乱”的序列,若序列已经有序,则快速排序会非常的慢。时间复杂度O(nlogn)。
4.归并排序
归并排序的思想是,把初始的序列表的每一个关键字都视为一个序列表,然后将相邻两序列表合并成一个序列表并排序,多次合并后最终达到只剩一个表。
/// <summary> /// 归并排序 /// </summary> /// <param name="array"></param> public void MergeSort(int[] array) { //归并排序 for (int i = 1; i < array.Length; i *= 2) { MergePass(array, i); } } private void Merge(int[] array, int low, int mid, int high) { int i = low; int j = mid + 1; int k = 0; int[] array2 = new int[high - low + 1]; while (i <= mid && j <= high) { if (array[i] <= array[j]) { array2[k] = array[i]; i++; k++; } else { array2[k] = array[j]; j++; k++; } } while (i <= mid) { array2[k] = array[i]; k++; i++; } while (j <= high) { array2[k] = array[j]; k++; j++; } for (k = 0, i = low; i < high; k++, i++) { array[i] = array2[k]; } } private void MergePass(int[] array, int gap) { int i =0; for (i = 0; i + 2*gap - 1 < array.Length; i += 2*gap) { Merge(array, i, i + gap - 1, i + 2*gap - 1); } if (i + gap - 1 < array.Length) { Merge(array, i, i + gap - 1, array.Length - 1); } }
归并排序是一种非常稳定的排序,在多数情况下排序时间都可以稳定到一个小的范围内。时间复杂度O(nlogn)。
5.堆排序
当序列满足Ki >= K(2i) && Ki >= K(2i+1)时,这个序列就是大顶堆,简单的说就是制造出一个二叉树,其根节点大于两子节点。堆排序就需要制造出这些大顶堆,则堆顶的就是最大的数,我们把堆顶移到序列末尾,再重新制造大顶堆,重复之前的步骤。
/// <summary> /// 堆排序 /// </summary> /// <param name="array"></param> public void HeapSort(int[] array) { for (int i = array.Length/2; i >= 1; i--) //非叶子节点的最大角标为Lenth/2 { HeapAdjust(array, i, array.Length - 1); } for (int i = array.Length - 1; i > 1; i--) { int temp = array[1]; array[1] = array[i]; array[i] = temp; HeapAdjust(array, 1, i - 1); } } private void HeapAdjust(int[] array, int s, int m) { int tmp = array[s]; for (int j = 2*s; j <= m; j *= 2) { if (j < m && array[j] < array[j + 1]) j++; if (tmp < array[j]) { array[s] = array[j]; s = j; } else break; } array[s] = tmp; }堆排序不适合对记录较少的文件做排序,但很适合对较大的文件排序。时间复杂度O(nlogn)
相关文章推荐
- python排序算法-冒泡排序,选择排序,直接插入排序,希尔排序,归并排序,快速排序,堆排序
- 排序算法: 冒泡排序, 快速排序,希尔排序,直接插入排序 ,直接选择排序,归并排序,堆排序
- 排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序
- 比较排序总结——直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序
- 排序算法汇总(选择排序 ,直接插入排序,冒泡排序,希尔排序,快速排序,堆排序)
- java五种内部排序(直接插入排序、希尔排序、快速排序、堆排序、归并排序)
- 排序算法(堆排序,归并排序,快速排序、选择排序、直接插入排序)
- 六、内部排序综合(九种)—插入类排序(直接插入、折半插入、希尔排序);交换类排序(冒泡、快速);选择类排序(简单选择、堆排序);二路归并排序;基数排序
- 排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序
- 6种排序算法及其比较 简单选择排序,堆排序,简单插入排序,希尔排序,冒泡排序,快速排序,归并排序
- 冒泡排序 快速排序 选择排序 堆排序 直接插入排序 希尔排序 归并排序
- 【Java】八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序 、快速排序、归并排序、堆排序和LST基数排序
- 牛客网Java刷题知识点之插入排序(直接插入排序和希尔排序)、选择排序(直接选择排序和堆排序)、冒泡排序、快速排序、归并排序和基数排序(博主推荐)
- 数据结构与算法:七种排序算法总结(冒泡排序、选择排序、直接插入排序、希尔排序、堆排序、归并排序、快速排序)
- C++排序:冒泡排序,简单选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序
- C++实现常用排序算法(快速排序、冒泡排序、希尔排序、折半插入排序、直接插入排序)
- [C++]数据结构:排序算法Part2----快速排序、归并排序、箱子排序、基数排序
- 常用的排序算法(快速排序、插入排序、希尔排序、堆排序、冒泡排序、选择排序、归并排序)
- 各种排序算法实现——基数排序、归并排序、插入排序、冒泡排序、选择排序、快速排序、堆排序、希尔排序
- 排序算法合集(插入排序,折半插入排序,希尔排序,冒泡排序,快速排序,简单选择排序,堆排序,归并排序)