排序算法--------插入排序和选择排序
2018-03-11 16:31
441 查看
1. 插入排序
直接插入将待排序元素插入到前面已经有序的数组中,直至将待排序元素全部插完(过程如下图)
具体步骤:
(1)比较待插入元素(key)和有序序列的最后一个元素(a[end]),如果 key>=a[end],直接插入,反之交换key和a[end]
(2)如果key< a[end],继续在有序区间里寻找小于key的元素(tmp),将key插入到tmp的后面
希尔排序
是直接插入排序的优化;当待排序元素较多时,直接插入的效率反而会变得很低,越接近有序的序列使用直接插入排序时,效率越高,故在进行插入排序之前进行预排序,使其待排序序列接近有序(如下图)
二者算法分析
稳定性
直接插入排序是稳定算法,排序码的相对位置不会改变希尔排序是不稳定算法,在进行预排序时,排序码的相对位置可能发生改变
时间复杂度
直接插入排序最优情况:待排序序列越接近有序,算法效率越高,时间复杂度为O(N)
最差情况:当待排序序列很大,并且不是很接近有序,算法效率大大降低,时间复杂度为O(n2n2)
希尔排序
希尔排序是直接插入排序的优化,但当待排序数列很大时,预排序过程效率会降低许多,时间复杂度为O(n2n2)
空间复杂度
空间复杂度都为O(1),在进行排序时,会创建临时常数个临时变量用于控制下标代码:
/*****************直接插入排序************/ void InsertSort(DataType* a, size_t n) { assert(a); int end; for (size_t i = 0; i < n - 1; ++i) { end = i; while (end >= 0 && a[end]>a[end + 1]) { //待插入序列大于有序序列的最后一个 Swap(&a[end], &a[end + 1]); --end; } } } /**********希尔排序******************/ void ShellSort(DataType* a, size_t n) { assert(a); //先进行预排序 int gap = n / 3 + 1;//进行预排序时的跨度 while (gap > 1) { for (size_t i = 0; i < n - gap; ++i) { size_t end = i; while (end >= 0 && a[end] >= a[end+gap]) { Swap(&a[end], &a[end + gap]); end -= gap; } } gap = gap / 3 + 1; } InsertSort(a, n); }
2.选择排序
选择排序4000
每遍历一次待排序序列,选出最大和最小的数,分别放在左边和右边的相应位置上,直到全部选出为止(如下图)
堆排序
将待排序序列建堆,每次将堆顶数据与堆尾数据进行交换,在进行堆的调整(部分过程图)
二者算法分析
稳定性
直接选择排序是不稳定算法,排序码的相对位置会发生改变堆排序是不稳定算法,在进行建堆和调整堆时,排序码的相对位置发生改变
时间复杂度
直接选择排序时间复杂度为O(N*N)
移动次数最好情况为0次
堆排序
建堆的时间复杂度为O(N*logN)
建堆后,每次排序时间复杂度为O(logN)
综上,堆排序的时间复杂度为O(N*logN)
空间复杂度
空间复杂度都为O(1),在进行排序时,会创建常数个临时变量用于控置下标需要占用一个临时空间,在交换数值时使用。
代码
/*******************选择排序*************/ void SelectSort(DataType* a, size_t n) { assert(a); size_t left = 0; size_t right = n - 1; while (left < right) { //排序结束条件,两边错过 size_t min = left; size_t max = left; for (size_t i = left; i <=right ; ++i) { //遍历数组,选出最小的数和最大的数 if (a[min] > a[i]) { //放到最左边 min = i; } if (a[max] < a[i]) { //放到最右边 max = i; } } //进行交换 Swap(&a[left], &a[min]); //当最大的数在最左边,需将max的位置置为最小值 if (max == left) { max = min; } Swap(&a[right], &a[max]); left++, right--; } } /*****************堆排序****************/ void HeapSort(DataType* a1, size_t n) { assert(a); //建堆,升序建大堆,降序建小堆 int i = (n - 2) >> 1; for (; i >= 0; --i) { AdjustDown(a, n, i); } for (int j = n-1;j>0; --j) { Swap(&a[j], &a[0]); AdjustDown(a, j, 0); } } //向下调整 void AdjustDown(DataType* a1, size_t n, size_t parent) { size_t child = parent * 2 + 1; while (child < n) { //选出左右孩子当中较大的 if ((child + 1) < n && a[child] < a[child + 1]) { ++child; } if (a[parent] < a[child]) { Swap(&a[parent], &a[child]); parent = child; child = parent * 2 + 1; } else { break; } } }
相关文章推荐
- 排序算法之直接插入排序
- 排序算法整理(C++):插入排序、交换排序、选择排序、归并排序
- 排序算法--插入排序(直接插入排序)
- 【数据结构】排序算法(一)之直接插入排序,冒泡排序
- 常见排序算法导读(4)[直接插入排序]
- 排序算法(快速排序、直接插入排序、直接选择、冒泡排序)
- 排序算法三:Shell插入排序
- 排序算法-之选择排序(直接选择排序,堆排序)
- 排序算法(三):插入排序
- 排序算法(3)-直接插入排序
- 排序算法---插入排序
- 基本排序算法及分析(一):插入排序,直接选择排序
- 四基础排序算法:插入排序、选择排序、冒泡排序、快速排序
- 排序算法--插入排序之希尔排序
- 排序算法之直接插入排序
- Java实现八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序等
- 各种排序算法的实现直接插入排序
- [排序算法]--直接插入排序的三种实现(Java)
- java排序之冒泡、插入、选择、快速等排序算法
- 排序算法之冒泡排序、选择排序、直接插入排序(java实现)