排序是計算機應用中的一個非常重要的操作。平常我們總會聽到一些算法,但是我們總是似懂非懂的寫着代碼,今天我將一般常見的排序算法進行一個總結。
本次總結只涉及內部排序(所謂內部排序是指在內存中進行的排序)
首先說一個概念:穩定排序與非穩定排序
如果一個序列中原來相同的元素,排序完成后,仍然保持着原來的順序,那么就成為穩定排序,反之就是非穩定排序。
插入排序
(1).直接插入排序(Straiht Insertion Sort)
算法描述:如果有一個已經排好序的序列 {R(20),R(35),R(88)},當要插入一個R(66)時,需要與各個元素進行比較,R(35)<R(66)<R(88),所以應該插在R(35)與R(88)直接。
算法開始時,取一個元素為原序列,然后重復執行上面的方法,將每個元素插入到序列中。
void InsertSort(SlList &L)
{
for(int i = 2; i < =L.lenght;i++)
{
if(LT(L[i],L[i-1])) //LT函數判斷兩個元素的大小
{
L[0] = L[i];
L[i] = L[i-1];
for(int j = i-2;LT(L[0],L[j]);j--)
{
L[j+1] = L[j];
}
L[j+1] = L[0];
}
}
此算法的時間復雜度為O(n2)
快速排序
快速排序是一種基於交換的排序方法,最常見的有冒泡排序(BubbleSort),快速排序(改進的冒泡排序)(QuickSort)
下面先說冒泡排序:
冒泡排序的基本思想是在一次排序中,將最大的元素沉入底部,然后縮小范圍,繼續進行。
具體的說:取第一個元素,然后與第二個元素進行比較,如果比第二個大,那么交換,否則,不交換,然后取第二個元素與第三個元素比較,同樣用前面的方法,大則交換,直到將最大的元素交換到最底部,這是第一遍排序結束,然后,縮小范圍,從第二個元素開始,在此運用上面的一遍排序方法。直到范圍縮小為一個元素的時候,排序結束。
下面是用c++語言描述的一個冒泡排序的算法:
int a[5] = {1,3,5,4,2};
for(int i=4;i>=0;i--)
for(int j = 0;j<=i;j++)
{
if(a[j]>a[j+1])
{
int temp;
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
for(int s = 0;s<5;s++)
cout<<a[s];
由於最近在學習匯編,所以在emu8086上寫了一個代碼段,實現冒泡排序:
;匯編冒泡排序算法
N equ 5
mov cx,N-1
j03:push cx
lea BX,A
j02:mov AL,[bx]
cmp AL,[BX+1]
jnb j01
xchg AL,[BX+1]
mov [BX],AL
j01:inc bx
loop j02
pop cx
loop j03
A db 1,2,3,4,
選擇排序
選擇排序(Selection Sort)的基本思想是,每一趟排序在n-i+1(i=1,2,3....,n-1)中選取關鍵字最小的記錄作為有序序列的第i個記錄。
(1)最為簡單的是簡單選擇排序(Sample Selection sort)
void selectsort(SqlList &L)
{
for(int i = 0;i < L.length;i++)
{
j = SelectMin*(L,i);//這個函數返回從i開始到結束的最小記錄
//的位置
if(i!=j) exchage(L[i],L[j]);
}
}
(2)樹形選擇排序(Tree Selection Sort),又稱錦標賽排序(Tournament sort),是一種按照錦標賽的思想,兩兩比較,然后在剩余的【n/2】個較小的元素中在進行兩兩比較,如此重復,最后選出最小的記錄為止。
(3)堆排序(Heap Sort)
先介紹一下大頂堆與小頂堆:
在一棵二叉樹中,如果所有父節點比兒子節點都大,稱這顆樹為大頂堆,反之,為小頂堆。
那么堆排序的思想便是將一個無序序列構建成大頂堆(或小頂堆)然后取出堆頂元素,再次調整這個堆,使之在此變成大頂推(或小頂堆),如此將所有元素取出,便排好了序。
歸並排序
歸並排序(Merging sort)
所謂歸並,簡單的講,就是將兩個有序的序列,合成一個新的有序表。我們用這個思想,可以把一個n個元素的序列,看成n個長度為1的子序列,然后利用歸並排序,兩兩合並,然后的到了n/2個長度為2的子序列,再次進行合並,重復上面的步驟,直到合並為一個序列,則歸並完成。
轉載請注明:來自witewolfe的博客園:http://www.cnblogs.com/gaoteng/archive/2012/03/18/2404828.html