常用排序算法总结

冒泡排序

时间复杂度:O(N²)

 

原理:从数组的第个位置开始两两比较array[index]和array[index+1],如果array[index]大于array[index+1]则交换array[index]和array[index+1]的位置,直到数组结束。

void Bubble(int array[], int size)
{
    int i,j;

    for(i=0; i<size; i++)
    {
        for(j=i+1; j<size; j++)
        {
            if(array[i]>array[j])
            {
                array[i]=array[i]^array[j];
                array[j]=array[i]^array[j];
                array[i]=array[j]^array[i];
            }
        }
    }

 

二、选择排序

时间复杂度:O(N^2),与冒泡排序相比减少了数组交换的次数

 

原理:选择个 array[0]作为标杆,然后循环找到除这个外最小的 (查找小于标杆的最小 ),交换这两个,这时最小就被放到了array[0]上,然后再将array[1]作为标杆,从剩下未排序的 中找到最小 ,并交换。

void Sort(int array[], int size)
{
    int i,j,k;

    for(i=0; i<size; i++)
    {
        k=i;
        for(j=i+1; j<size; j++)
        {
            if(array[j]<array[k])
            {
                k=j;
            }
        }

        if(i!=k)
        {
            array[i]=array[i]^array[k];
            array[k]=array[k]^array[i];
            array[i]=array[i]^array[k];
        }
    }
}

 

三、插入排序

时间复杂度:插入排序对随即顺序的序列的时间复杂度也为O(N^2),但是对于基本有序的序列进行排序时间复杂度为O(N)

适用:一般不用在数据大于1000的场合或者重复排序超过200数据项的序列使用插入排序

 

原理:插入排序的思想是数组是部门有序的,然后将无序的部分循环插入到已有序的序列中。

void InsertSort(int array[], int size)
{
    int i,j,temp;

    for(i=2; i<size; i++)
    {
        temp=array[i];

        for(j=i-1; j>=0 && array[j]>temp; j--)
        {
            array[j+1]=array[j];
        }

        array[j+1]=temp;
    }

}

 

四、希尔排序/缩小增量排序

时间复杂度:n的1.2次幂

适用:适合于数据量在5000以下并且速度并不是特别重要的场合。

 

原理:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。

void shellSort(int array[], int size)
{
    int i,j,temp;
    int increment=size;

    do
    {
        increment=increment/3+1;
        for(i=increment+1; i<size; i++)
        {
            temp=array[i];

            for(j=i-increment; j>=0 && array[j]>temp; j-=increment)
            {
                array[j+increment]=array[j];
            }

            array[j+increment]=temp;
        }
    }while(increment>1);

}

 

五、堆排序

时间复杂度:O(N*logN)

适用:适合于数据量非常大的场合(百万数据)

 

原理:利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。
其基本思想为(大顶堆):
1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无须区;
2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n];
3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。

//array是待调整的堆数组,i是待调整的数组元素的位置,nlength是数组的长度
//本函数功能是:根据数组array构建大根堆
void HeapAdjust(int array[],int i,int nLength)
{
    int nChild;
    int nTemp;
    for(;2*i+1<nLength;i=nChild)
    {
        //子结点的位置=2*(父结点位置)+1
        nChild=2*i+1;
        //得到子结点中较大的结点
        if(nChild<nLength-1&&array[nChild+1]>array[nChild])++nChild;
        //如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
        if(array[i]<array[nChild])
        {
            nTemp=array[i];
            array[i]=array[nChild];
            array[nChild]=nTemp;
        }
        else break; //否则退出循环
    }
}
//堆排序算法
void HeapSort(int array[],int length)
{
    int i;
    //调整序列的前半部分元素,调整完之后第一个元素是序列的最大的元素
    //length/2-1是最后一个非叶节点,此处"/"为整除
    for(i=length/2-1;i>=0;--i)
    HeapAdjust(array,i,length);
    //从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
    for(i=length-1;i>0;--i)
    {
        //把第一个元素和当前的最后一个元素交换,
        //保证当前的最后一个位置的元素都是在现在的这个序列之中最大的
        array[i]=array[0]^array[i];
        array[0]=array[0]^array[i];
        array[i]=array[0]^array[i];
        //不断缩小调整heap的范围,每一次调整完毕保证第一个元素是当前序列的最大值
        HeapAdjust(array,0,i);
    }
}

你可能感兴趣的:(排序算法)