若干常用(內部)排序演算法的總結

2021-06-06 06:18:11 字數 3328 閱讀 9946

實現**中會出現巨集

typedef int datatype;

#define swap( a, b )

1. 插入排序演算法

類似數學歸納法的描述:

① 起始時a[beg]的元素位置不變(此時a[beg]這乙個元素已經有序)

② 假設a[beg]..a[i](beg<=i<=end-1)已經排好序, 對a[i+1]..a[end],依次將a[i+1],...,a[end]插入到a[beg],...,a[i]的指定位置

將①②結合可得到插入排序的偽**:

for i=beg+1:1:end

t = a[i]

for j=i-1:-1:beg

if t < a[j]

a[j+1] = a[j]

else

break

a[j+1] = t

void insertsort( datatype* a, int beg, int end )

else

}a[j+1] = t;

}}

2.選擇排序

基本思想,類似數學歸納法的描述:

① 起始時找到a[beg]..a[end]中的最小元素,將該元素與a[beg]交換;

② 假設a[beg]..a[i](beg<=i<=end-1)已經有序且a[i+1]..a[end]的任一元素大於a[beg]..a[i], 從a[i+1]..a[end]選擇最小的元素新增到a[beg]..a[i]末尾,亦即將a[i+1]與a[i+1]..a[end]中的最小元素交換位置

將①②結合可得到選擇排序的偽**:

for i=beg:1:end-1

find k s.t. a[k] = min( a[i+1]..a[end] )

exchange a[i] and a[k]

實現:

void selectionsort( datatype* a, int beg, int end )

} if ( k != i )

}}

3. 氣泡排序

基本思想,類似數學歸納法的描述:

① 起始進行第一輪冒泡,對a[beg]..a[end]從後往前,如果a[j-1]>a[j], 則交換a[j-1]和a[j]的值(beg<=j-1② 假設a[beg]..a[i](beg<=i<=end-1)已經排好序且a[i+1]..a[end]的任一元素大於a[beg]..a[i],對a[i+1]..a[end]從後往前冒泡:若a[j-1]>a[j],交換a[j-1]和a[j], (i+1<=j-1將①②結合可得到氣泡排序偽**:

for i = beg:1:end-1

for j = end:-1:i+1

if a[j-1] < a[j]

then exchange a[j-1] and a[j]

實現:

void bubblesort( datatype* a, int beg, int end )

} }}

4. 快速排序

基本思想:分治策略

首選選取乙個樞紐元p,通常選取p=a[beg],將陣列餘下的元素通過與p比較,將原陣列劃分為兩部分:小於p的部分和大於p的部分,然後構建新的陣列,使得a[j]的元素值為p,a[beg]..a[j-1]的值全都小於p,a[j+1]..a[end]的值全部大於p;然後分別對子陣列a[beg]..a[j-1]和a[j+1]..a[end]進行快速排序。

實現如下(遞迴版本):

void quicksort( datatype* a, int beg, int end )

swap( a[j], a[beg] );

quicksort( a, beg, j-1 );

quicksort( a, j+1, end );

}

對以上基本的快速排序演算法可進行一下兩方面的改進:

① 樞紐元p的選擇對快速排序演算法的效率有很大影響,為了使得快速排序演算法對所有可能情況的排序時間複雜度盡可能低,通常在陣列中選取乙個隨機的元素作為樞紐元;具體的實現策略也很簡單,就是現在陣列中隨機選取乙個元素,然後將該元素與陣列第乙個元素交換,並將該元素作為樞紐元,接下來便可直接套用如下實現的演算法;

② 雖然插入排序等時間複雜度為o(n^2)的演算法比快速排序的平均時間複雜度o(nlogn)要大,但經過試驗測試,當待排序的資料個數小於20個時,插入排序等演算法的實際消耗時間比快速排序演算法要小(因為快速排序演算法是乙個遞迴的演算法,通常遞迴的效率是比較低的);因此可以考慮當快速排序遞迴到陣列元素個數小於某一值n(n<20)時,不再採用快速排序繼續遞迴,而是採用插入排序等演算法。

隨機選取樞紐元素的快速排序演算法實現:

#include #include // windows

void quicksort1( datatype* a, int beg, int end)

swap( a[beg], a[j] );

quicksort1( a, beg, j-1 );

quicksort1( a, j+1, end );

}

當陣列元素小於16時採用插入排序演算法,實現如下:

void quicksort2( datatype* a, int beg, int end )

p = a[beg];

i = beg;

j = end+1;

for ( ;; )

swap( a[beg], a[j] );

quicksort2( a, beg, j-1 );

quicksort2( a, j+1, end );

}

綜合 quicksort1 和 quicksort2 的快速排序演算法實現:

void quicksort3( datatype* a, int beg, int end )

srand( (unsigned int)time(0) );

n = rand()%(end-beg+1) + beg;

swap( a[beg], a[n] );

i = beg;

j = end+1;

p = a[beg];

for ( ;; )

swap( a[beg], a[j] );

quicksort3( a, beg, j-1 );

quicksort3( a, j+1, end );

}

快速排序演算法的非遞迴實現可參見:快速排序演算法的遞迴與非遞迴實現 。

常用的內部排序演算法

通過乙個簡單的選單,分別實現下列排序要求,採用幾組不同資料測試各排序演算法的效能 比較次數和移動次數 及穩定性。實現簡單選擇排序 直接插入排序和氣泡排序 實現折半插入排序 實現希爾排序演算法 實現快速排序演算法 遞迴和非遞迴 實現堆排序演算法。1 輸入 根據選單提示選擇排序演算法,輸入一組待排序資料...

排序演算法(內部排序)總結

排序是計算機應用中的乙個非常重要的操作。平常我們總會聽到一些演算法,但是我們總是似懂非懂的寫著 今天我將一般常見的排序演算法進行乙個總結。本次總結只涉及內部排序 所謂內部排序是指在記憶體中進行的排序 首先說乙個概念 穩定排序與非穩定排序 如果乙個序列中原來相同的元素,排序完成後,仍然保持著原來的順序...

預覽文章 排序演算法(內部排序)總結

排序是計算機應用中的乙個非常重要的操作。平常我們總會聽到一些演算法,但是我們總是似懂非懂的寫著 今天我將一般常見的排序演算法進行乙個總結。本次總結只涉及內部排序 所謂內部排序是指在記憶體中進行的排序 首先說乙個概念 穩定排序與非穩定排序 如果乙個序列中原來相同的元素,排序完成後,仍然保持著原來的順序...