1. 程式人生 > >八種排序演算法(冒泡,插入,選擇,快速,堆,歸併,希爾,計數) 待續。。

八種排序演算法(冒泡,插入,選擇,快速,堆,歸併,希爾,計數) 待續。。

各種排序演算法實現及比較

1. 氣泡排序,時間複雜度O(N^2),“冒泡”:每次將最大的數放到陣列末尾

兩層迴圈,外層為趟數,內層實現每趟將最大的數移到陣列尾部。每一趟針對未排序的陣列,從頭開始每次比較相鄰的兩個數,如果後面的數比前面的數小,就交換這兩個數,一趟比較完之後最大的數就交換移到了陣列最尾部。

void BubbleSort(vector<int> array)
{
    int len=array.size();
    for(int i=0;i<len;i++)
    {
        for(int j=1;j<len-i;j++)
        {
            if(array[j]<array[j-1])
                {
                    int temp=array[j];
                    array[j]=array[j-1];
                    array[j-1]=temp;
                }
        }
    }
}

2. 插入排序,時間複雜度O(N^2),“插入”:每次將數插入排序陣列中合適的位置

兩層迴圈,外層迴圈的i將陣列分為兩部分,左邊是排好序的,右邊是沒有排序的,內層迴圈j指向沒排序的第一個數字,先存下這個數字temp,然後將這個數字依次與前面的數字(從j-1開始到0)比較,如果當前數字比temp大,就將其後移一位,直到不滿足這個條件,退出迴圈,將當前位置填上temp。

void InsertSort(vector<int> array)
{
    int len=array.size();
    for(int i=0;i<len;i++)
    {
        int j=i;
        int temp=array[j];
        while(j>0)
        {
            if(temp<array[j-1])
            {
                array[j]=array[j-1];
                j--;
            }
            else
                break;
        }
        array[j]=temp;
    }
}

3. 選擇排序,時間複雜度O(N^2),“選擇”:每次遍歷未排序陣列選擇最小的數與第一個數交換

兩層迴圈,外層迴圈的i將陣列分為兩部分,左邊是排好序的,右邊是沒有排序的,內層迴圈j指向沒排序的第一個數字。每次遍歷右邊沒有排序的陣列,找到最小的數字,與第一個位置(j)的數字交換。

void SelectSort(vector<int> array)
{
    int len=array.size();
    for(int i=0;i<len-1;i++)
    {
        int k=i;
        for(int j=i+1;j<len;j++)
        {
            if(array[j]<array[k])
                {
                    k=j;
                }
        }
        if(k!=i)
        {
            int temp=array[i];
            array[i]=array[k];
            array[k]=temp;
        }
    }
}

4. 快速排序,時間複雜度O(NlogN)

分兩步,首先在陣列中選擇一個基準數字,然後遍歷陣列,使得比基準數小的數都移到左邊,比基準數大的都移到右邊,然後對左右兩邊的陣列進行快速排序,通過遞迴完成。

函式partition實現的功能:將基準數小的數都移到左邊,比基準數大的都移到右邊,並且返回基準值位置。

void QuickSort(vector<int> array, int low, int high)
{
	if(low>=high)
		return;
	int pos=partition(array, low, high);
	if(pos>low)
	{
		QuickSort(array, low, pos-1);
	}
	if(pos<high)
	{
		QuickSort(array, pos+1, high);
	}
}

重點是partition函式,用兩個前後指標完成兩兩交換,當i=j時停止迴圈,將最左邊數字設為基準值,i從pos+1先往後走一直遇到第一個大於base的,j往前走一直遇到第一個小於base的,交換i和j位置的值,。最後結束迴圈的時候,交換小於基準值陣列的最右邊位置的值和基準值位置的值,要注意i指向的有可能是小於基準值陣列的最右邊的值(array[i]<base),也可能是大於基準值陣列最左邊的值(array[i]>base),如果是第二種情況,則應該交換i-1位置的。

int partition(vector<int> &array, int low, int high)
{
	int pos=low;
	int base=array[pos];
	int i=low+1;
	int j=high;
    while(i<j)
    {
        while(i<j&&array[i]<=base)
        {
            i++;
        }
        while(i<j&&array[j]>=base)
        {
            j--;
        }
		swap(array[i],array[j]);
    }
	int p;
	if(array[i]>base)
		p=i-1;
	else
		p=i;

	swap(array[p],array[pos]);
	return p;
}

4. 堆排序

5. 歸併排序