常用排序算法(二)選擇排序、快速排序

常用排序算法(一)插入排序、希爾排序、冒泡排序

常用排序算法(三)歸併排序、堆排序、基數排序

1 選擇排序

       選擇排序也是一種簡單直觀的排序算法。它的工作原理很容易理解:初始時在序列中找到最小(大)元素,放到序列的起始位置作爲已排序序列;然後,再從剩餘未排序元素中繼續尋找最小(大)元素,放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。算法平均時間複雜度O(n2)。

一種用C++實現的選擇排序算法如下:

void SelectSort(int a[], int n) 
{
	for (int i = 0; i < n - 1 ; i++)
	{
		for (int j = i + 1 ; j < n; j++)
		{
			if (a[j] < a[i])
			{
				int min = a[j];
				a[j] = a[i];
				a[i] = min;
			}
		}
	}
}

       上面示例代碼中,第二層循環需要找出從下標 i 開始的最小值,對於每一個比a[i]小的值a[j]都進行交換,下面進行改進:

void SelectSort(int a[],int n) //選擇排序
{
    int mix,temp;
    for(int i=0;i<n-1;i++) //每次循環數組,找出最小的元素,放在前面,前面的即爲排序好的
    {
        mix=i; //假設最小元素的下標
        for(int j=i+1;j<n;j++) //將上面假設的最小元素與數組比較,交換出最小的元素的下標
            if(a[j]<a[mix])
                mix=j;
        //若數組中真的有比假設的元素還小,就交換
        if(i!=mix)
        {
            temp=a[i];
            a[i]=a[mix];
            a[mix]=temp;
        }
    }
}

        改進後的代碼,內層循環只進行判斷,並記錄下最小值的下標,然後在外層循環只需交換一次數據,稍微加快了速度。

        注意選擇排序與冒泡排序的區別:冒泡排序通過依次交換相鄰兩個順序不合法的元素位置,從而將當前最小(大)元素放到合適的位置;而選擇排序每遍歷一次都記住了當前最小(大)元素的位置,最後僅需一次交換操作即可將其放到合適的位置。

2 快速排序

  1. 基本思想:(分治)

    • 先從數列中取出一個數作爲key值;
    • 將比這個數小的數全部放在它的左邊,大於或等於它的數全部放在它的右邊;
    • 對左右兩個小數列重複第二步,直至各區間只有1個數。
  2. 輔助理解:挖坑填數

    • 初始時 i = 0; j = 9; key=72
      由於已經將a[0]中的數保存到key中,可以理解成在數組a[0]上挖了個坑,可以將其它數據填充到這來。
      從j開始向前找一個比key小的數。當j=8,符合條件,a[0] = a[8] ; i++ ; 將a[8]挖出再填到上一個坑a[0]中。
      這樣一個坑a[0]就被搞定了,但又形成了一個新坑a[8],這怎麼辦了?簡單,再找數字來填a[8]這個坑。
      這次從i開始向後找一個大於key的數,當i=3,符合條件,a[8] = a[3] ; j-- ; 將a[3]挖出再填到上一個坑中。
      數組:72 - 6 - 57 - 88 - 60 - 42 - 83 - 73 - 48 - 85
       0   1   2    3    4    5    6    7    8    9
    • 此時 i = 3; j = 7; key=72
      再重複上面的步驟,先從後向前找,再從前向後找。
      從j開始向前找,當j=5,符合條件,將a[5]挖出填到上一個坑中,a[3] = a[5]; i++;
      從i開始向後找,當i=5時,由於i==j退出。
      此時,i = j = 5,而a[5]剛好又是上次挖的坑,因此將key填入a[5]。
      數組:48 - 6 - 57 - 88 - 60 - 42 - 83 - 73 - 88 - 85
       0   1   2    3    4    5    6    7    8    9
    • 可以看出a[5]前面的數字都小於它,a[5]後面的數字都大於它。因此再對a[0…4]和a[6…9]這二個子區間重複上述步驟就可以了。
      <數組:48 - 6 - 57 - 42 - 60 - 72 - 83 - 73 - 88 - 85
       0   1   2    3    4    5    6    7    8    9

平均時間複雜度:O(N*logN)

void QuickSort(int a[], int l, int r) {
	if (l >= r)
		return;

	int i = l; int j = r; int key = a[l];//選擇第一個數爲key

	while (i<j) {

		while (i<j && a[j] >= key)//從右向左找第一個小於key的值
			j--;
		if (i<j) {
			a[i] = a[j];
			i++;
		}

		while (i<j && a[i]<key)//從左向右找第一個大於key的值
			i++;

		if (i<j) {
			a[j] = a[i];
			j--;
		}
	}
	a[i] = key;
	QuickSort(a, l, i - 1);//遞歸調用
	QuickSort(a, i + 1, r);//遞歸調用
}

 

發佈了36 篇原創文章 · 獲贊 183 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章