几种排序

来源:互联网 发布:制作项目进度表 软件 编辑:程序博客网 时间:2024/05/16 19:25

Sort

排序是经典问题,关于排序的算法也有很多,根据平时的使用习惯,下面简单总结了几种常见的,简单易懂的排序算法。其中部分内容参考了数据结构自考网,还有各位大神,小鬼的blog

 

目录:(按策略划分)

交换排序

       冒泡排序(BubbleSort

       快速排序(QuickSort

插入排序

       直接插入排序(InsertionSort

       希尔排序(Shell Sort

选择排序

       直接选择排序(Selection Sort

       堆排序(HeapSort

以上几种排序方法比较

 

BubbleSort

经典冒泡排序,两项比较,如果大小关系和关键字相反就交换位置

#include<stdio.h>

void main()

{

       int i,j,t;

       int a[9]={9,2,1,5,6,3,4,7,8};

       for(i=1;i<9;i++)

              for(j=0;j<8;j++)

                     if(a[j]>a[i])

                     {

                            t=a[j];a[j]=a[i];a[i]=t;

                     }

       for(i=0;i<9;i++)

              printf("%d ",a[i]);

       printf("/n");

}

另:

算法思想:将被排序的记录数组R[1..n]垂直排列,每个记录R[i]看作是重量为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R:凡扫描到违反本原则的轻气泡,就使其向上"飘浮"。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。

QuickSort

快速排序(qsort),分治递归思想制定标志变量,以其分割数组,并对前数组,后数组分别递归调用函数,直到数组长度为1,则完成排序

#include <iostream>  

#include <stdlib.h>  

#include <ctime>  

using namespace std;  

int partition(int *A,int p,int r)  //数组分割

{  

    int i,j,x;  

    x=A[r];       //指定标志值

    i=p-1;            //保证第一次找到的小于,等于X的数被换到

    for(j=p;j<r;j++)  //a[0],第二个放到a[1]……

        if(A[j] <= x) //大于X的数不会使i变大

        {  

            i++;

            swap<int>(A[i],A[j]);    

        }  

    swap<int>(A[i+1],A[r]);   //i个数都小于a[r]

    return i+1;     //返回a[r],即分割数组的标志值位置

}  

void quicksort(int *A,int p,int r)  

{  

    if(p >= r)  

        return ;  

    int q=partition(A,p,r);  

    quicksort(A,p,q-1);   //q位置的数不用参与排序,因为当前位置就是

    quicksort(A,q+1,r);   //其正确位置

}  

void Show(int *A,int p,int r)  

{  

    for(int i=p;i<=r;i++)  

        cout<<A[i]<<" ";  

    cout<<endl;  

}   

void main()  

{  

    int i;  

    int A[10];  

    srand((unsigned int)time(NULL));  

    for(i=0;i<10;i++)  

        A[i]=rand()%20;  

    Show(A,0,9);  

    quicksort(A,0,9);  

    Show(A,0,9);  

    system("pause");     

}

 

InsertionSort

插入排序,每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中的适当位置,直到全部记录插入完成为止。

默认当前项前面的序列有序,并在前面的序列中查找第一个比当前项大(小)的数,找到后,把该数以及其后面的数全部后移一位,空出来的位置就是当前的位置。

插入排序的操作很类似打牌时整理手中的牌,很有意思的方法。

#include<stdio.h>

void main()

{

       int i,j,t;

       int a[9]={9,2,1,5,6,3,4,7,8};

       for(i=1;i<9;i++)

       {

              if(a[i]<a[i-1])//R[i].key大于等于有序区中所有的keys,则R[i]

                       //应在原有位置上

              {

                     t=a[i];

                     for(j=i-1;j>=0;j--)

                            if(a[j]>t)

                            {

                                   a[j+1]=a[j];

                                   a[j]=t;

                            }

                            else break;

              }

       }

       for(i=0;i<9;i++)

              printf("%d ",a[i]);

       printf("/n");

}

 

另:希尔排序实质上就是分组插入排序,效率较直接插入排序有很大提高,但是不稳定。

 

SelectionSort

选择排序,在待排数据中查找最小(大)值放在第一位,然后在剩下的数中查找第二小(大)的数放在第二位,……依次操作

#include<stdio.h>

void main()

{

       int i,j,t,min;

       int a[9]={9,2,1,5,6,3,4,7,8};

       for(i=0;i<9;i++)

       {

              min=i;

              for(j=i+1;j<9;j++)

                     if(a[j]<a[min])

                            min=j;   

              t=a[i];a[i]=a[min];a[min]=t; //t做存储单元,也可以用a[0]做存储单元

       }

       for(i=0;i<9;i++)

              printf("%d ",a[i]);

       printf("/n");

}

 

直接选择排序时就地排序,是不稳定的排序。

 

HeapSort

堆排序

堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆。根结点的关键字是堆里所有结点关键字中最大者,称为大根堆。堆中任一子树亦是堆。

堆排序可通过树形结构保存部分比较结果,可减少比较次数。

堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

步骤:

建堆(假设是大根堆),把堆顶元素a[1]和最后一个元素a[n]交换位置,则a[n]就是最大值;然后以a[1]a[n-1]为对象,调整建堆,再把堆顶元素和最后一个元素(现在是a[n-1])交换,则a[n-1]a[n]就是有序的了。以此重复操作即可。

 

 

以上几种排序方法比较

平均时间:

(1)    平方阶(O(n2))排序

一般称为简单排序,例如直接插入、直接选择和冒泡排序;

2)线性对数阶(O(nlgn))排序

     如快速、堆排序;

3O(n1+)阶排序

     £是介于01之间的常数,即0<<1,如希尔排序;

各种排序方法比较

     简单排序中直接插入最好,快速排序最快,当文件为正序时,直接插入和冒泡均最佳。

影响排序效果的因素

     因为不同的排序方法适应不同的应用环境和要求,所以选择合适的排序方法应综合考虑下列因素:

       1待排序的记录数目n

2记录的大小(规模)

3关键字的结构及其初始状态;

4对稳定性的要求;

5语言工具的条件;

6存储结构;

7时间和辅助空间复杂度等。

不同条件下,排序方法的选择
(1)n较小(n≤50),可采用直接插入或直接选择排序。

     当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插入,应选直接选择排序为宜。

(2)若文件初始状态基本有序(指正序),则应选用直接插入、冒泡或随机的快速排序为宜;

(3)n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序;

     快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;

     堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。

原创粉丝点击