选择排序和插入排序
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 }
以上是关于选择排序和插入排序的主要内容,如果未能解决你的问题,请参考以下文章
直接插入排序 ,折半插入排序 ,简单选择排序, 希尔排序 ,冒泡排序 ,快速排序 ,堆排序 ,归并排序的图示以及代码,十分清楚