幾種常見簡單排序算法

- 簡單選擇排序
循環遍歷整個數組,每次遍歷都是從當前待填充位置開始,找出未排序集合中的最小值,每次找到更小值都記錄其值和位置信息,遍歷完成後,將最小值與當前待填充點 進行交換(也就是說需要同時保留着兩個位置信息,一個爲當前待填充位置,一個是搜索到的待交換位置,如果是指針則需要兩個指針)。繼續下一個位置,直到外循環到達數組尾。

#include <iostream>
using namespace std;
int main()
{
    int a[10]={23,11,6,33,14,99,23,2,14,20};
    int smallest;
    int smallpos;
    for(int i=0;i<10;i++)
    {
        cout<<a[i]<<' ';
    }
    for(int i=0;i<9;i++)
    {
        smallest=a[i];
        smallpos=i;
        for(int j=i+1;j<10;j++)
        {
            if(a[j]<smallest)
            {
                smallest=a[j];
                smallpos=j;
            }
        }
        a[smallpos]=a[i];
        a[i]=smallest;
    }
    cout<<endl;
    for(int i=0;i<10;i++)
    {
        cout<<a[i]<<' ';
    }
    return 1;
}

- 插入排序
插入排序的原理爲在未排序集合中選擇一個值在已排序集合中尋找其合適的位置插入。首先整個集合默認爲未排序集合,從頭開始遍歷,得到一個未排序數據並記錄,然後從該數據位置開始往回遍歷尋找插入位置,首先判斷待插入位置是否爲首位,如果是則直接插入。否則,每次將待插入值與待插入位置前一位的值相比,若比待插入值大,則該值往後移動一位,待插入位置前移一位,否則將待插入值填入待插入位置。

#include <iostream>
using namespace std;
/******插入排序***********/
int main()
{
    int a[10]={23,11,6,33,14,99,23,2,14,20};
    int cur;
    for(int i=0;i<10;i++)
    {
        cout<<a[i]<<' ';
    }
    cout<<endl;
    for(int i=1;i<10;i++)
    {
        cur=a[i];
        for(int j=i;j>=0;j--)
        { 
            if(j==0)
            {
                a[j]=cur;
            }
            else if(a[j-1]>cur)
            {
                a[j]=a[j-1];
            }
            else
            {
                a[j]=cur;
                break;
            }
        }
     } 
    for(int i=0;i<10;i++)
    {
        cout<<a[i]<<' ';
    }
    return 1;
}

-交換排序

循環遍歷數組,每次比較相鄰兩個元素,將大的放在後面,小的放在前面,直到達到最後交換元素位置,每次達到最後交換元素位置並完成交換後,就將最後交換元素位置前移一位。直至最後交換元素位置與首位重合,則排序結束,退出循環。
下面程序中last表示最後交換元素的位置。

#include <iostream>
using namespace std;
/*******交換排序***********/
int main()
{
    int a[10]={23,11,6,33,14,99,23,2,14,20};
    int last=9;
    for(int i=0;i<10;i++)
    {
        cout<<a[i]<<' ';
    }
    cout<<endl;
    while(last>0)
    {
        for(int i=0; i < last; i++ )
        {
            if(a[i]>a[i+1])
            {
                int tmp=a[i];
                a[i]=a[i+1];
                a[i+1]=tmp;
            }
        }
        last--;
    }
    for(int i=0;i<10;i++)
    {
        cout<<a[i]<<' ';
    }   
    return 1;
}

-歸併排序
其原理是,將兩個有序集合同時遍歷,每次比較兩個集合中當前位置的元素,將較小的元素賦給合併集合相應位置,然後合併集合待填充位置右移一位,較小元素所在集合當前位置右移一位,繼續比較,同時還需要判斷哪個集合先遍歷完,對於另外一個還有剩餘元素的集合,則直接把剩餘的元素直接賦給合併集合剩餘的位置中。但是由於集合是亂序的,因而需要將集合不斷分割至單元素集合(可認爲是有序集合),然後再進行集合的的重新組合,組合得到的新集合則是有序的,如此回溯直至回到從原始集合中分開的兩個子集爲有序集合,再進行最後一次合併,完成原始集合的排序。
總體而言,其步驟是遞歸地分割原始集合,直至集合中只有單元素,然後往回結合成有序集合,即排序的過程是從下往上的。

#include <iostream>
using namespace std;
int mergesort(int* array,int i,int j);
int merge(int* arr,int i,int  k,int j);
int main()
{
    int a[10]={23,11,6,33,14,99,23,2,14,20};
    int n=9;
    for(int i=0;i<=n;i++)
    {
        cout<<a[i]<<' ';
    }
    cout<<endl;
    mergesort(a,0,n);
    for(int i=0;i<=n;i++)
    {
        cout<<a[i]<<' ';
    }
    return 1;
}
int mergesort(int* array,int i,int j)
{
    if(i<j)      //數組中只剩下一個元素的返回條件
    {
        int k=(i+j)/2 ;
        mergesort(array,i,k);
        mergesort(array,k+1,j);
        merge(array,i,k,j);   //對兩個有序自己進行排序
    }
    return 0;
}
int merge(int* arr,int i,int k,int j)
{
    int ipos=i;      //用於遍歷左集合
    int kpos=k+1;   //用於遍歷右集合
    int mpos=0;     //額外分配的空間位置
    int* tmparr=new int[j-i+1];  //額外分配空間存儲排序數組
    while(ipos<=k || kpos<=j)
    {
        if(ipos>k)            //表示左集合數據合併完畢 
        {
//若左集合已經沒有元素而右集合還有,直接將右集合元素複製到剩餘空間中
            while(kpos<=j)
            {
                tmparr[mpos]=arr[kpos];
                kpos++;
                mpos++;
            }
            continue;
        }
        else if(kpos>j)        //右集合數據合併完畢 
        {
//同理,右集合沒有元素了,左集合還有,則把剩下元素直接複製到額外空間
            while(ipos<=k)
            {
                tmparr[mpos]=arr[ipos];
                ipos++;
                mpos++;
            }
            continue;
        }       
        if(arr[ipos]<arr[kpos])
        {
             tmparr[mpos]=arr[ipos];
             ipos++;
             mpos++;
        }
        else
        {
            tmparr[mpos]=arr[kpos];
            kpos++;
            mpos++;
        }
    }
    ipos=i;
    int tmpi=0;
    while(ipos<=j)
    {
        arr[ipos]=tmparr[tmpi];
        ipos++;
        tmpi++;
    }
    delete tmparr;
    return 0;
}

這裏寫圖片描述
圖中箭頭序號表示的是執行順序,實現框爲原始數據順序,虛線框爲排序過後順序。

-快速排序
快速排序與歸併排序有點相似,都是需要分割,但是其過程卻是相反的,歸併排序是先分割,然後回溯時候進行排序,當回溯到原集合的時候完成排序。而快速排序是先排序(確定基準元素位置,以及其他元素所處集合)然後分割,再確定分割後的集合中基準元素位置,遞歸進行,當分割至最後一個元素則意味着最後一個元素的位置確定了,即整個集合完成排序。
算法步驟:
1、從序列中選出一個元素(此處挑選序列第一個元素),作爲pivot(基準元素);
2、數組重新排列,將小於基準值的放在基準前面,大於基準值的放在基準後面,重新排列完成後,基準將會被放在其正確的位置,也就是說,這一步驟實際上可以認爲是確認了pivot元素的正確位置的。具體做法就是,分別從右、從左開始遍歷序列,當在右邊遇到小於基準值的則停下,左邊遇到大於基準值的則停下,然後二者進行交換,直至二者相遇停止。
3、當確認了pivot的正確位置之後,則可以通過該基準值,將整個序列進行“分割”,然後對“分割”的序列再進行排序,即回到步驟1,只是排序序列爲“分割”後的序列,遞歸進行,分別對基準左右兩邊的序列作爲遞歸序列。

#include <iostream>
using namespace std;

int qsort(int* array,int l,int r);
int sort(int* array,int lp,int rp);

int main()
{
    int a[10]={23,11,6,33,14,99,23,2,14,20};
    for(int i=0;i<10;i++)
    {
        cout<<a[i]<<' ';
     }
     cout<<endl;
    qsort(a,0,9);
    for(int i=0;i<10;i++)
    {
        cout<<a[i]<<' ';
    }
    return 1;
}

int qsort(int* array,int l,int r )
{
    int pos;
    if(l<r)
    {
        pos=sort(array,l,r);
        qsort(array,l,pos-1);
        qsort(array,pos+1,r);
    }
}
//確定基準的位置
int sort(int* array,int lp,int rp)
{
    int lpos=lp;
    int rpos=rp; 
    int pivot=array[lp];
    while(lpos<rpos)
    {
        while(array[rpos]>pivot)
                rpos--;
        while( (lpos<rpos) && array[lpos]<=pivot)
        {
                lpos++;
        }
        if(lpos<rpos)
        {
            int tmp=array[lpos];
            array[lpos]=array[rpos];
            array[rpos]=tmp;
            lpos++;
            rpos--;
            continue;
        }
     }
     array[lp]=array[rpos];
     array[rpos]=pivot;
     return rpos;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章