选择排序和插入排序

Posted holly-blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了选择排序和插入排序相关的知识,希望对你有一定的参考价值。

选择排序

选择排序的思想非常简单,很多书或技术Blog都讲的很好,这里不赘述了,直接给出代码

 1 void selectionSort(int arr[],int n){
 2     for(int i = 0;i<n;i++){
 3         int minIdx = i;
 4         for(int j = i+1;j<n;j++){
 5             if(arr[j]<arr[minIdx])
 6                 minIdx = j;
 7         }
 8         swap(arr[i],arr[minIdx]);
 9     }
10 }

如果考虑通用性,可以使用模板函数

 1 template<typename T>
 2 void selectionSort(T arr[],int n){
 3     for(int i = 0;i<n;i++){
 4         int minIdx = i;
 5         for(int j = i+1;j<n;j++)
 6             if(arr[j]<arr[minIdx])
 7                 minIdx = j;
 8         swap(arr[i],arr[minIdx]);
 9     }
10 }

插入排序

插入排序的思想非常简单,无论是经典教材《算法导论》还是不少技术文章都以扑克牌为例,手里的牌是有序的,每拿到一张新牌会为它在排好序的牌中找出合适的位置插入。

代码如下:

 1 void insertion_sort(int arr[],int n){
 2     for(int i =1;i<n;i++){
 3         for(int j = i+1;j<n-1;j++){
 4             if(arr[j+1]<arr[j])
 5                 swap(arr[j],arr[j+1]);
 6             else
 7                 break;
 8         }
 9     }
10     return;
11 }

 

对比选择排序,虽然都是O(N^2)级别的,但是,我们发现,插入排序可以提前结束退出,所以理论上讲插入排序应该比选择排序快,这里,可以写个测试测试一下。测试结果,发现,比选择排序慢,仔细观察,我们发现,在第二层循环中,每当出现逆序(比较操作)就swap(),swap()函数的实现,我们在大学刚学习高级语言程序设计时应该就学过,它需要一个临时变量,三句实现,需要花费三倍于比较时间。对于数组来说,还有访问操作,那能不能改进插入排序算法,使之在第二层循环中只交换一次呢。当然,答案是可以的。

首先,我们把要考查的当前元素复制一份,接着将该元素副本与已排好序的元素比较,只要比当前元素大,就后移,最终不再移动的位置就应该是当前要考察元素的位置,等有时间了,我会把这段思考过程用图片的形式演示出来,下面先放上代码

 1 void insertion_sort_opti(int arr[],int n){
 2     for(int i = 0;i<n;i++){
 3         int cur = arr[i] // copy the current element
 4         int j;//define j,j is the aultimate index of the curr
 5         for(int j = i;j>0&& arr[j-1]>cur;j--){
 6             arr[j] = arr[j-1];
 7         }
 8         arr[j] = cur;
 9     }
10     return;
11 }

 

希尔排序

之所以把希尔排序列在这里,是因为希尔排序也是一种插入排序,希尔排序整体的思路就是插入排序的延伸,在插入排序中,每一次都和之前的一个元素进行比较,而希尔排序是每一次都和之前的第h个元素进行比较,h从一个很大的值逐渐减小为1,一步步将一个完全无序的数组变成一个近乎有序的数组,变成有序性越来越强的数组,直到最后变成一个有序的数组,不难理解,希尔排序会更高效,因为插入排序对于有序数组的可以达到线性的时间复杂度,既然是插入排序的延伸,依然给出未优化的和优化的版本,实现如下:

V1

 1 void shell_sort(int arr[],int n){
 2     int h = 1;//make sure the last step h =1
 3     while(h*3<n) h = h*3+1;
 4     while(h>=1){
 5         // like to insertion sort,start with teh second element
 6         for(int i = 1;i<n;i++){
 7             for(int j = i;j>=h;j-=h){ //j starts with current(i-th)
 8                 if(arr[j]<arr[j-h]) //element,compare with (j-h)th
 9                     swap(arr[j],arr[j-h]); //element,if less than
10                 else                       // swap
11                     break;
12             }
13         }
14         h/=3;
15     }
16 }

优化版本

 

 1 void shell_sort_opti(int arr[],int n){
 2     int h = 1;
 3     while(h<n/3) h = h*3+1;
 4     while(h>=1){
 5         for(int i = 1;i<n;i++){
 6             int curr = arr[i];
 7             int j;
 8             for(j = i;j>=h;j-=h)
 9                 if(arr[j]<curr)
10                     arr[j] = arr[j-h];
11             arr[j] = curr;
12         }
13         h/=3;
14     }
15 }

 

以上是关于选择排序和插入排序的主要内容,如果未能解决你的问题,请参考以下文章

直接插入排序 ,折半插入排序 ,简单选择排序, 希尔排序 ,冒泡排序 ,快速排序 ,堆排序 ,归并排序的图示以及代码,十分清楚

选择排序和插入排序

《算法》笔记 3 - 选择排序插入排序希尔排序

python实现时间复杂度平均为N^2的冒泡选择插入排序

python实现时间复杂度平均为N^2的冒泡选择插入排序

python实现时间复杂度平均为N^2的冒泡选择插入排序