資料結構與演算法 第11部分 排序

2021-10-03 11:24:38 字數 3499 閱讀 6663

1:直接插入排序

演算法步驟:

1)設待排度的記錄儲存在陣列r[1...n]中,可以把第乙個記錄r[1]看作乙個有序序列。

2)依次將r[i](i = 2,…,n)插入到已經排好序的序列r[1..i - 1]中,並保持有序性。

void straightinsertsort(int r,int n)  //直接插入排序

r[0] = r[nindex]; //r[nindex]暫存到r[0]中,r[0]有監視哨的作用

r[nindex] = r[nindex - 1]; //r[nindex-1]後移一位

for (int j = nindex - 2; r[j] > r[0]; j--) //從後向前尋找插入位置,逐個後移,直到找到插入位置

r[j + 1] = r[0]; //將r[0]插入到r[j+1]位置

}}

2:氣泡排序

氣泡排序是一種最簡單的交換排序演算法,通過兩兩比較關鍵字,如果逆序就交換,

使關鍵字大的記錄像泡泡一樣冒出來放在尾部。重複執行若干次氣泡排序,最終得到有序序列。

演算法步驟:

1)設待排度的記錄儲存在陣列r[1..n]中,首先第乙個記錄和第二個記錄關鍵字比較,若逆序則交換;

然後第乙個記錄和第二個記錄關鍵字比較,…,以此類推,直到第n - 1個記錄和第n個記錄關鍵字比較完畢為止。

第一趟排序結束,關鍵字最大的記錄在最後乙個位置。

2)第二趟排序,對前n - 1個元素進行氣泡排序,關鍵字次大的記錄在n - 1位置。

3)重複上述過程,直到某一趟排序中沒有進行交換記錄為止,說明序列已經有序。

void bubblesort(int r,int n) //氣泡排序

int temp = r[i]; //交換兩個記錄

r[i] = r[i + 1];

r[i + 1] = temp;

} }}

3:快速排序

演算法步驟:

1)首先取陣列的第乙個元素作為基準元素pivot = r[low]。i = low,j = high。

2)從右向左掃瞄,找小於等於pivot的數,如果找到,r和r]交換,i++。

3)從左向右掃瞄,找大於pivot的數,如果找到,r和r]交換,j--。

4)重複步驟2~步驟3,直到i和指標重合,返回該位置mid - i,該位置的數正好是pivot元素。

5)至此完成一趟排序。此時以mid為界,將原資料分為兩個子串行,左側子串行元素

都比pivot小,有側子串行元素都比pivot大,然後再分別對這兩個子串行進行快速排序。

int partition(int r,int low,int high)//劃分函式

if(i演算法改進:

從上述演算法可以看出,每次交換都是在和基準元素進行交換,實際上沒必要這樣做

我們想把原序列分成以基準元素為界的兩個子串行,左側子串行小於等於基準元素,右側子串行大於基準元素。

我們可以從右向左掃瞄,找小於等於pivot的數r[j],然後從左向右掃瞄,找大於pivot的數r[i],讓r[i]和r[j]交換,

一直交替進行,直到i和j碰頭為止,這時將基準元素與r[i]交換即可。這樣就完成了一次劃分過程,但交換元素的個數少了很多。

int partition2(int r,int low,int high)//劃分函式

while (i < j && r[i] <= pivot)

if(ipivot)

swap(r[i],r[low]);//r[i]和r[low]交換

return i;//返回最終劃分完成後基準元素所在的位置

}

void quicksort(int r,int low,int high)//實現快排演算法

int mid = partition(r, low, high); //基準位置

quicksort(r, low, mid - 1);//左區間遞迴快排

quicksort(r, mid + 1, high);//右區間遞迴快排

}

4:合併排序

演算法設計:合併排序是採用分治策略實現對n眾元素進行排序的演算法:

(1)分解一一將待排序元素分成大小大致相同的兩個子串行。

(2)治理——對兩個子串行進行合併排序。

(3)合併一一將排好序的有序子串行進行合併,得到最終的有序序列。

void merge(int a, int low, int mid, int high)//合併函式

//將陣列中剩下的元素放置b中

while (i <= mid)

while (j <= high)

for (i = low, k = 0; i <= high; i++)

delete b;//釋放空間

}void mergesort(int a, int low, int high)//合併排序

int mid = (low + high) / 2;//取中點

mergesort(a, low, mid);//對a[low:mid]中的元素合併排序

mergesort(a, mid + 1, high);//對a[mid+1:high]中的元素合併排序

merge(a, low, mid, high);//合併

}

5:選擇排序

演算法步驟:每次從待排序序列中選擇乙個最小的放在最前面。

1)設待排序的記錄儲存在陣列r[1..n]中,首先從r[1..n]中選擇乙個關鍵字最小的記錄

r[k],r[k]與r[1]交換。

2)第二趟排序,從r[2..n]中選擇乙個關鍵字最小的記錄r[k],r[k]與r[2]換。

3)重複上述過程,經過n - 1趟排序,得到有序序列。

void selectsort(int r,int n) //選擇排序

k = j; //記錄最小值下標

}if(k != i)

}}

6:堆排序

演算法步驟:

1)構建初始堆。

2)堆頂和最後乙個記錄交換,即r[1]和r[n]交換,將r[1..n - 1]重新調整為堆。

3)堆頂和最後乙個記錄交換,即r[1]和r[n - 1]交換,將r[1..n - 2]重新調整為堆。

4)迴圈n - 1次,得到乙個有序序列。

「下沉」操作:堆頂與左右孩子比較,如果比孩子大,則已調整為堆;如果比孩子小,

則與較大的孩子交換,交換到新的位置後,繼續向下比較,從根結點一直比較到葉子。

void sink(int k,int n)//下沉操作

if (r[k] >= r[j])//比較大的孩子大

else

k=j;//k指向交換後的新位置,繼續向下比較,一直下沉到葉子

}}void creatheap(int n)//構建初始堆

}void heapsort(int n)//堆排序

}

演算法 面試題 16 16 部分排序

給定乙個整數陣列,編寫乙個函式,找出索引m和n,只要將索引區間 m,n 的元素排好序,整個陣列就是有序的。注意 n m盡量最小,也就是說,找出符合條件的最短序列。函式返回值為 m,n 若不存在這樣的m和n 例如整個陣列是有序的 請返回 1,1 示例 0 len array 1000000 解法 如果...

資料結構與演算法 第03部分 棧與佇列(棧)

1 棧定義 define maxsize 100 預先分配空間,這個數值根據實際需要預估確定 typedef struct sqstack sqstack 2 構造乙個空棧s bool initstack sqstack s 構造乙個空棧s s.ptop s.pbase ptop初始為pbase,空...

資料結構與演算法 第02部分 線性表

1 結點定義 typedef struct lnode lnode,linklist linklist為指向結構體lnode的指標型別2 構造乙個新的結點 bool initlist l linklist lnew,int ndata 0 構造乙個新的結點 lnew data ndata lnew ...