排序算法

来源:互联网 发布:免费的顶级域名 编辑:程序博客网 时间:2024/06/08 17:00

冒泡排序

  1. void bubblesort(int a[], int n)
  2. {
  3.   for(int i=0; i<n-1; i++)
  4.     for(int j=0; j<n-1-i; j++)
  5.        if(a[j]>a[j+1])
  6.           swap(a[j],a[j+1]);
  7. }
  8.  
  9.  //或者

  10. void bubblesort(int a[], int n)
  11. {
  12.    for(int i=0; i<n; i++)
  13.      for(int j=i; j<n; j++)
  14.         if(a[i]>a[j])
  15.            swap(a[i],a[j]); 
  16. }
  17.    
  18.  


比较次数:1+2+......+N-1

优化版冒泡排序

  1. void bubblesort(int a[], int n)       n2
  2. {
  3.    bool flag = true;

  4.    for(int i=0; i<n-1 &&falg; i++)
  5.      {
  6.        flag = false;

  7.         for(int j=1; j<n-i; j++)
  8.           if(a[j]<a[j-1])
  9.             {
  10.               swap(a[j],a[j-1]);
  11.                flag = true;
  12.             }
  13.        }
  14. }
  15. /* 设置一个标志域flag,如果某一趟排序发生了变换,那么flag为true。
  16.  *  如果某一趟排序没有发生交换,则说明序列已经有序了,不必再进行继续的比较操作,此时flag为false
  17.  */


——————————————————————————————————————————————————————————

选择排序

 思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

  1. void Selectsort(int a[], int n)           n2
  2. {
  3.    for(int i=0; i<n-1 ; i++)
  4.      {
  5.         min = i;

  6.         for(int j=i+1; j<n; j++) 

  7.              if(a[j] <a[min])
  8.                
  9.                    min = j;
  10.       }
  11.  
  12.     if(min != i)
  13.     {
  14.       swap(a[min], a[i]);
  15.     }
  16.      

归并排序

[cpp] view plain copy
  1. //将有序数组a[]和b[]合并到c[]中  
  2. void MemeryArray(int a[], int n, int b[], int m, int c[])    nlog2n
  3. {  
  4.     int i, j, k;  
  5.   
  6.     i = j = k = 0;  
  7.     while (i < n && j < m)  
  8.     {  
  9.         if (a[i] < b[j])  
  10.                     c[k++] = a[i++];  
  11.            else  
  12.                     c[k++] = b[j++];   
  13.     }  
  14.   
  15.     while (i < n)  
  16.                    c[k++] = a[i++];  
  17.   
  18.     while (j < m)  
  19.                    c[k++] = b[j++];  
  20. }  

可以看出合并有序数列的效率是比较高的,可以达到O(n)。


插入排序

如果a[j]前一个数据a[j-1] > a[j],就交换a[j]和a[j-1],再j--直到a[j-1] <= a[j]。这样也可以实现将一个新数据新并入到有序区间,从小到大排序。

[cpp] view plain copy
  1. void Insertsort3(int a[], int n)         n2
  2. {  
  3.     int i, j;  
  4.     for (i = 1; i < n; i++)  
  5.         for (j = i - 1; j >= 0 && a[j] > a[j + 1]; j--)  
  6.             Swap(a[j], a[j + 1]);  
  7. }  

快速排序


思想

快速排序采用的思想是分治思想。

快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正 确位置,排序完成。所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。

举例说明一下吧,这个可能不是太好理解。假设要排序的序列为

2 2 4 9 3 6 7 1 5 首先用2当作基准,使用i j两个指针分别从两边进行扫描,把比2小的元素和比2大的元素分开。首先比较2和5,5比2大,j左移

2 2 4 9 3 6 7 1 5 比较2和1,1小于2,所以把1放在2的位置

2 1 4 9 3 6 7 1 5 比较2和4,4大于2,因此将4移动到后面

2 1 4 9 3 6 7 4 5 比较2和7,2和6,2和3,2和9,全部大于2,满足条件,因此不变

经过第一轮的快速排序,元素变为下面的样子

[1] 2 [4 9 3 6 7 5]

之后,在把2左边的元素进行快排,由于只有一个元素,因此快排结束。右边进行快排,递归进行,最终生成最后的结果。

代码

复制代码
int quicksort(int a[], int left, int right){
if(left < right){
int key = a[left];
int low = left;
int high = right;
while(low < high)
               {
while(low < high && a[high] > key)
                        {
high--;
}
a[low] = a[high];
while(low < high && a[low] < key)
                       {
low++;
}
a[high] = a[low];
}
a[low] = key;
quicksort(a,left,low-1);
quicksort(a,low+1,right);
}
}


分析

快速排序的时间主要耗费在划分操作上,对长度为k的区间进行划分,共需k-1次关键字的比较。

最坏情况是每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准左边的子区间为空(或右边的子区间为空),而划分所得的另一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减少一个。时间复杂度为O(n*n)

在最好情况下,每次划分所取的基准都是当前无序区的"中值"记录,划分的结果是基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数:O(nlgn)

尽管快速排序的最坏时间为O(n2),但就平均性能而言,它是基于关键字比较的内部排序算法中速度最快者,快速排序亦因此而得名。它的平均时间复杂度为O(nlgn)。

讲解:https://zhidao.baidu.com/question/498320427100370484.html

通俗的说:找到一个基准值,从右边找比它小的,如果是互换

                                                    从左边找比它大的,如果是互换

                      如果不符合了,第一轮结束,此时左右两边都重复执行如上操作


堆排序:http://www.cnblogs.com/mengdd/archive/2012/11/30/2796845.html




1 0