zoukankan      html  css  js  c++  java
  • 选择排序和插入排序

    选择排序

    选择排序的思想非常简单,很多书或技术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 }
  • 相关阅读:
    vmalloc详解
    SSD 页、块、垃圾回收
    ext2文件系统
    slub分配object
    slab分配object
    ACCESS_ONCE的作用
    CFS理论模型
    代码规范
    About Me
    SDOI R2 咕咕记
  • 原文地址:https://www.cnblogs.com/Holly-blog/p/9310395.html
Copyright © 2011-2022 走看看