演算法 排序演算法(四) 交換排序

2021-07-28 07:26:03 字數 4013 閱讀 4853

本篇博文旨在介紹排序演算法中的交換排序;介紹了氣泡排序和快速排序的基本思想;介紹了氣泡排序和快速排序的幾種實現方法;從時間複雜度和空間複雜度進行了分析;並用c++實現了氣泡排序和快速排序

依次比較相鄰的兩個數,如果前者比後者大,就進行交換。一輪下來可以將大的元素先放到最右邊的位置。然後縮小區間,再次從頭開始第二輪的氣泡排序,這一次將次大的數放到相應位置。再次從頭冒泡,直到區間只有1個數。

按照公升序舉例

1、比較相鄰兩個數的大小,如果前面的數比後面的大,就進行交換

2、如果沒有比較的區間的尾部,依次向後冒泡

3、這一輪會將最大的數冒到區間的最右邊,然後區間右邊減少乙個數,重複上述步驟

4、直到區間縮小為1

當排序到一定趟數時,其剩下的元素可能已經有序,不需要進行冒泡了

這時,再次冒泡只會白白的浪費時間

解決方法只需要加乙個標誌位,用來判斷該次排序有沒有進行交換資料。

如果一趟排序下來並沒有進行資料的交換,就表示剩下的元素已經有序了,直接結束排序

從演算法中,我們可以分析出,氣泡排序第一趟排序排n-1次,第二趟排n-2,第三趟n-3....

所以其時間複雜度為o(n* n)

優化後,雖然一定程度上減少了資料的比較次數,在最好情況(有序)下,時間複雜度是o(n)

但是在最壞情況(逆序)下,仍是o(n* n)的演算法

所以優化並不能減少氣泡排序的數量級

#pragma once 

#includeusing namespace std;

void print(int* arr, size_t n)

cout << endl;

}//公升序

templatestruct greater

};//降序

templatestruct less

};//氣泡排序

template>

void bubblesort(t* arr,size_t n)

} //表示已經有序,直接返回

if (false == true)

return; }}

void testbubblesort()

; bubblesort>(arr, 10);

cout << "氣泡排序:" << endl;

print(arr, 10);

}

每次排序將乙個數放到合適的位置上,並以此位置劃分成兩個區間;

達到左邊的數都比該數小,右邊的數都比該數大;

然後遞迴進行兩個區間的排序

演算法步驟

1、用左指標left和右指標right兩個值表示著排序的區間,並將右指標right所指向的值存為key值,也就是當前的坑

2、從左指標向右找比key值大的數,找到了停止,將左指標指向的數填入坑中,然後讓左指標指向的數成為新坑

3、接下來從右指標向左找比key值小的數,找到了停止,將右指標指向的數填入新的坑中

4、反覆第2、3步,直到兩個指標相遇

5、將第1步保留的key值放入最後乙個坑中,並以此劃成兩個區間

**實現

//方法1:挖坑法

int partsort1(int* a, int left, int right)

a[left] = key;

return left;

}

演算法步驟

1、用左指標left和右指標right兩個值表示著排序的區間

2、從左指標向右找比key值大的數,找到了停止

3、接下來從右指標向左找比key值小的數,找到了停止

4、交換左指標和右指標數的指向

5、反覆第2、3、4步,直到兩個指標相遇

**實現

int partsort(int* arr, int left, int right)

swap(arr[left],arr[key]);

return left;

}

演算法步驟

1、cur指向left,prev指向cur的前乙個

2、當cur遇到的數比key值(最右邊的值)大時,繼續往前走;

若cur遇到的值比key值小,讓prev向前走一步並和cur進行交換

3、cur走到最右邊時,讓prev向前走一步並和cur進行交換

4、將區間劃分為兩個部分,直到區間內只有乙個數

**實現

//方法3:前後指標法

int partsort3(int* a, int left, int right)

if (++prev != cur)

std::swap(a[prev], a[cur]);

return prev;

}

整趟排序利用單趟排序的返回值將其分成兩個區間

然後分別對兩個區間進行快速排序

void quicksort(int* a, int left, int right)

}

快速排序採用了二分的思想

最好情況,每次劃分區間都將區間平分成兩份,此時的時間複雜度為o(n* logn)

最壞情況,每次劃分區間,都導致其中乙個區間為空,此時的時間複雜度為o(n* n)

但是一般情況下,我們認為快速排序的時間複雜度為o(n* logn)

空間複雜度為o(logn)

由於快速排序這裡採用了遞迴的演算法,當對小區間進行快速排序時,反不如直接插入排序更為高效

所以當元素個數小於一定的數量時,採用直接插入排序

**實現

void quicksort(int* a, int left, int right)

int mid = partsort3(a, left, right);

quicksort(a, left, mid - 1);

quicksort(a, mid + 1, right);

}}

之前我們分析,快速排序最好的情況就是每次劃分區間,兩邊的區間大小是一致的

所以我們通過在左,右,中三個下標中找到不大不小的那個數,將其放到最右邊作為key值進行區間的劃分

從而盡可能的保證了劃分後的兩個區間大小相差不會很大,從而提高了快速排序的效率

**實現

//三數取中法

int getmidindex(int* a, int left, int right)

else//mid left

}

例如挖坑法,其他方法也加到開頭即可

//方法1:挖坑法

int partsort1(int* a, int left, int right)

a[left] = key;

return left;

}

之前實現快速排序的單趟排序都是運用了遞迴,一聽到遞迴這兩個字就應該考慮到,當數量大時可能到時棧溢位的問題

因為遞迴就是一種壓棧的過程,因此我們可以用庫中自帶棧來實現非遞迴的快速排序

從而減少了遞迴導致的呼叫函式的開銷,效率也大大提高

**實現

#include//非遞迴

void quicksortnonr(int* a, size_t n)

if (mid + 1 < right)}}

排序演算法 交換排序

交換排序的基本思想 兩兩比較待排序元素的關鍵字,發現兩個元素的次序相反時則進行交換,直到沒有反序的元素為止。1.氣泡排序 交換排序 演算法 氣泡排序 bubble sort 輸入 待排序元素的陣列,待排序元素個數 輸出 原理 通過無序區中相鄰元素間關鍵字的比較和位置的交換,使關鍵字最小的元素如氣泡一...

排序演算法 交換排序

基本思想 在乙個待排序序列中,兩兩比較元素的排序碼,如果不滿足次序要求則進行交換,直到整個排序序列滿足要求。思想 對待排序序列從前向後,依次比較相鄰元素的排序碼,若發生逆序,則進行交換。實現 include void bubblesort int p,int n if flag 減少不必要的比較 r...

交換排序演算法

快速排序 為啥叫快速排序,因為速度快,效率高 1.先找乙個數作為基準。作為基準的這個數,一趟排下來,左邊的數必小於它,右邊的數必大於它,也就是說,它找到了自己的位置。2.將兩個指標i,j分別指向表的起始 基準 和最後的位置。3.比較j指標的數字是否小於基準,j 直到j小於基準,交換位置 4.比較i指...