演算法筆記 演算法初步之排序

2021-10-02 13:39:38 字數 4759 閱讀 5796

**壹.直接插入排序**
自己的理解:

插入排序是將陣列當成摸牌

1.預設的將第一張牌a[0]認為已經在手上了,從i=1開始摸牌,暫時放在temp裡,即temp=a[i]

2.j=i表示當前放在temp裡的牌應該放的位置,即a[j],為了確定是哪一張牌應該放在這個位置,需要用temp與a[j-1](當前應該放的位置前乙個位置)比較,符合排序條件就放誰。

3.排序條件:

公升序:如果摸上來的牌比手上某乙個牌要小,將該牌向後挪乙個位置,將摸上來的牌插入空缺

降序: 如果摸上來的牌比手上某乙個牌要大,將該牌向後挪乙個位置,將摸上來的牌插入空缺

如果不滿足條件,就將摸上來的牌放在末位

#include

void

insertsort

(int

*a1,

int n)

;int

main

(void);

int*p = a;

insertsort

(p,10);

for(p;p10;p++

)return0;

}void

insertsort

(int

*p,int n)

}

輸出:

公升序:-43 -21 0 5 12 24 34 56 65 689

降序:689 65 56 34 24 12 5 0 -21 -43

注意事項:

在insertsort函式中,內層for迴圈,判斷條件

1.不能把a[j]>temp,移至迴圈內部寫成if語句,否則會出錯

2.不能把所有的temp改寫成a1【i】,因為是在同乙個陣列中進行操作,若果出現後移一位的錯作的時候,a【i】所帶表的值是變化的,所以需要乙個中間變數temp來儲存移位之前a【i】所表示的值。

**貳.希爾排序**
希爾排序是:將大陣列按照每間隔d個單位的元素組成乙個小陣列,再在小組內進行插入排序,讓小陣列在大陣列中實現間隔d個單位仍然是有序的。不斷縮小,間隔d來達到大陣列全部有序的目的。

具體思路:

1.將大陣列按照元素每間隔d=n/2構成乙個小陣列

2.各小陣列內,進行插入排序,與一般插入排序不同的是,小陣列內各元素的下標對應關係(以第乙個,二個分組為例,d=5)是:第一組(0,5,10,…)、第二組(1,6,11)。所以在各個小組內第一次摸上來的牌,下標應該是5,6,7等等,即i=d,i=d+1等

3.為了方便描述各個小組之間的元素,都採用以第乙個分組第一次摸上來的牌的下標i為基準,用i自增來表示。

**為:

//注釋都是在插入排序的基礎上備註的

void

shell_sort

(int

*p,int n)}}

```cpp

在這裡插入**片

**壹、氣泡排序**
自己的理解:

對陣列進行i=n-1趟排序,每趟排序排出乙個最大或者最小值出來,最後乙個元素不用排序,所以是n-1趟,每結束依次就i–。

每一趟的操作:對下標在[0,i]之間的元素,進行排序

void

bubblesort

(int

*p,int n)

if(flag ==0)

break

;//沒有發生交換就說明已經完成了排序

}}

**貳、快速排序**
思路:

1.設立乙個基準元素a,使左邊所有元素不超過a;右邊所有元素不小於a。

2.遞迴的將整個陣列劃分成若干跟小區間,重複進行1.

3.小區間內實現1是依靠兩個指標left,right,不斷向中間移動,當right所指元素小於a,就將其放置在left所指位置;left所指元素大於a時就將其放在right所指位置。

4.由於在陣列元素排列較為有序的時候,快速排序的效率不高,所以生成乙個隨機位置,作為基準元素temp,以打亂陣列的有序性,提高效率。

5.同樣用分割函式和合併函式,來完成。

//合併函式

intpartition

(int a,

int left,

int right)

a[left]

= temp;

//基準元素放在中間。

return left;

}//分割函式

void

quicksort

(int a,

int left,

int right)

合併寫法:

void

quicksort

(int a,

int left,

int right)

a[i]

= temp;

quicksort

(a,left,i-1)

;quicksort

(a,i+

1,right);}

}

ps:1.合併函式內:對右側的處理應該先做,因為將基準元素賦值給了temp,等同於空出了該位置,將右側小於基準元素的值放過來不會對陣列產生影響,但是如果先操作左側就會出現覆蓋掉右側元素的情況。

2.生成隨機數語句:int p = round(1.0rand()/rand_max(right-left)+left);

需要包含的標頭檔案:time.h,stdlib.h。

並且需要加上:srand((unsigned)time(null))

3.rand()函式生成的隨機數是介於【0,rand_max】之間的。

想要得到[a,b]範圍內的隨機數,方法為rand()%(b-a+1)+a。

如果需要生成區間的數值太大,就先生成乙個[0,1]範圍內的浮點數,然後乘以這個區間加上下限即可。

也就是:round(1.0rand()/rand_max(right-left)+left);

**壹、簡單選擇排序**
選擇:自己的理解:

簡單選擇排序就是進行n-1趟操作,操作的次數用i表示,每趟操作都選出乙個最小值或者最大值。選出來之後將最大值或者最小值與第i個元素進行交換。

void selectsort(int

*arr,int n) }

int temp = arr[k]

; arr[k]

= arr[i]

; arr[i]

= temp;

}}

輸出:

-43 -21 0 5 12 24 34 56 65 689

貳、堆排序
具體思路:見**排序演算法(三)之堆排序

自己的理解:

1.核心:堆排序就是建立在最大堆,或者最小堆的不斷調整的基礎上進行排序的。

2.排序思路:以公升序,使用最大堆為例

由於最大堆的根,也就是對頂永遠都是最大的元素,於是總是將堆頂元素放在陣列的最後乙個位置,並且不再參與堆的調整。

#include

using

namespace std;

/*--------------調整函式---------------*/

void

percdown

(int

*h,int p,

int n)

h[parent]

= temp;

//最後把原來的堆頂元素放在沒有他更小的位置上

}void

heap_sort

(int

*h,int n)

1.遞迴實現二路排序:

將陣列劃分成無數個區間,遞迴的合併就行。

注意事項:

歸併排序的核心思路就是,用乙個分割函式,遞迴的將陣列分割成【left,mid】和【mid+1,right】兩部分,直到只剩下乙個元素,就是分割出來的最小區間,然後就是用合併函式,將兩個區間按照一定的順序合併,然後返回到分割函式。

//合併函式

void

merge

(int merge,

int l1,

int r1,

int l2,

int r2)

;//使用臨時陣列來排序,暫時儲存資料

while

(i<=r1 && j<=r2)

else

}while

(i<=r1)

while

(j<=r2)

for(

int i=

0;i//分割函式,遞迴實現

void

mergesort

(int sort,

int left,

int right)

}

2.非遞迴實現

思路是:使用步長為2的step表示起始區間,在區間內將其分成左右兩部分,並進行和並

step成指數遞增

//分割函式非遞迴實現

void

mergesort

(int a,

int n)}}

}

強調:內層迴圈控制了排序的起始位置,如果採用0為起始下標,i=0;

演算法初步之排序

對輸入的n個數進行排序並輸出。輸入的第一行包括乙個整數n 1 n 100 接下來的一行包括n個整數。可能有多組測試資料,對於每組資料,將排序後的n個整數輸出,每個數後面都有乙個空格。每組測試資料的結果佔一行。5 5 4 3 1 21 2 3 4 5 include int main else pri...

演算法筆記之貪心初步

題目描述 某市計程車計價規則如下 起步4公里10元,即使你的行程沒超過4公里 接下來的4公里,每公里2元 之後每公里2.4元。行程的最後一段即使不到1公里,也當作1公里計費。乙個乘客可以根據行程公里數合理安排坐車方式來使自己的打車費最小。例如,整個行程為16公里,乘客應該將行程分成長度相同的兩部分,...

演算法筆記演算法初步(4 1排序)

1.選擇排序 每次在待排序區間中選擇最小的往前排,隨著排序已排序區間不斷後移 include 選擇排序 int a 6 int n 5 int main int n 5 int main int n 5 int main printf n sort a,a 5 a 0 a 4 五個數 for int...