基礎複習 內排序 查詢演算法

2021-08-02 11:17:03 字數 3193 閱讀 2289

內排序

void mkarr(int **arr, int size)
void checksorted(int *arr, int size, int flag) 

}else

}printf("all right\n");

}

1.插入排序

假設陣列的前i個數已經排好序,然後將第i+1個數插入到前i個中,只到n個數都插入到自己的位置。

平均時間複雜度 o(n2),當序列已經排好序時時間複雜度低o(n),當序列是逆序時時間複雜度最高為o(n2)。插入過程都是從後往前,所以演算法是穩定的。

void insertsort(int *arr, int size) 

arr[j + 1] = tmp;

}}

2.選擇排序

假設前i-1個元素已經排好序,從第i到n個元素中選擇最小的放到第i個位置,只到第n個元素。

因為每次選擇都要把剩下的元素全部檢查一遍所以,演算法的最低、最高、平均時間複雜度都是o(n2)。選擇排序在第一輪的最小元素是最後乙個,這樣第乙個元素就直接被交換到最後,如果序列中有和第乙個元素相同的元素,那他們的相對位置肯定變了,所以演算法是不穩定的。

void selectionsort(int *arr, int size) 

int tmp = arr[i];

arr[i] = arr[min];

arr[min] = tmp;

}}

3.氣泡排序

從前到後相鄰的元素比較大小,如果前面的元素大於後面的,兩個元素交換,如果沒有大於,下乙個元素繼續與相鄰的下乙個元素進行比較,每一輪可以確定乙個最大的元素。

每一輪冒泡都要把所有相鄰元素進行比較,所以演算法的最低、最高、平均時間複雜度都是o(n2)。冒泡方向不變,所以演算法是穩定的。

void  bubblesort(int *arr, int size) }}

}

4.快排

選擇乙個基準元素對陣列進行分割,比基準大的在一邊,比基準小的在一邊,分割結束後基準元素已經排好序。再對左右兩個部分遞迴進行分割,直到整個陣列有序。

平均時間複雜度o(nlogn),當演算法每次選擇基準值時都選擇到最大或最小元素時,演算法時間複雜度最高o(n2),每次都選到中間值時時間複雜度最低為o(nlogn)。劃分的過程是從兩邊向中間走,所以快速排序不穩定。

// 劃分陣列,返回基準值位置

int parition(int *arr, int size)

while (arr[low] < tmp && low < high)

low++;

if (low < high)

}arr[pivot] = tmp;

return pivot; //返回基準元素的位置

}void quicksort(int *arr, int size)

int pivot = parition(arr, size);

quicksort(arr, pivot);

quicksort(arr + pivot + 1, size - pivot - 1);

}

5.歸併排序

把兩個相對有序的子串行合併成乙個.

時間複雜度 o(nlogn),空間複雜度 n。兩個序列歸併的過程相同排序欄位的元素不會發生交換,所以是穩定的。

// 合併兩個子串行

void merge(int *arr, int *res, int start1, int end1, int start2, int end2)

while (start1 <= end1)

arr[ix++] = res[start1++];

while (start2 <= end2)

arr[ix++] = res[start2++];

}void mergesort(int *arr, int *res, int start, int end)

6.堆排序

對陣列的前n個元素建堆,將第乙個元素與第n個元素交換,然後對前n-1元素建堆.

重新建堆的時間複雜度為o(logn),所以演算法的最好、最壞、平均時間複雜度都o(nlogn)。建堆過程中排序字段相同元素的父節點可能不相同,導致相對順序有可能改變,所以堆排序不穩定。

void heapsort(int* arr, int start, int end) 

if (i * 2 + 2

<= end && arr[i] < arr[i * 2 + 2])

}// 最大的元素與最後乙個元素交換,然後繼續對start到end-1建立大根堆

tmp = arr[start]; arr[start] = arr[end]; arr[end] = tmp;

end--;

}}

7.shell排序

先用增量x對原陣列進行劃分,(0,x,2*x…)/(1,1+x,1+2*x…)/(2,2+x,2+2*x…)…

然後在每個劃分上執行插入排序,然後增量減半x=x/2,繼續執行,知道x=1;

與插入排序相同,當原序列有序是時間複雜度最低為o(n),平均和最高時間複雜度都為o(n2)。相同排序關鍵字的元素可能會劃入不同的子串行,導致相對位置變化,所以shell排序是不穩定的。

void shellinsertsort(int *arr, int start, int end, int step) 

}void shellsort(int* arr, int start, int end)

}}

查詢

8.順序查詢

時間複雜度o(n)

int linersearch(int *arr, int target, int start, int end) 

return -1; // 查詢失敗

}

9.二分查詢

假設原序列有序(遞增),先查詢序列中間的元素,如果相等返回座標,如果小於目標則繼續在後一半中進行二分查詢,大於時在前一半進行二分查詢.

時間複雜度o(logn)

int binsearch(int *arr, int target, int start, int end)

基礎排序演算法複習

1.計數排序 計數排序的四個步驟 a.初始化c 0 k 為0 b.對於每個元素a i c a i c記錄a中各個元素出現的次數,比如中,c 1 2,c 2 0,c 3 1 c.對於i 1 to k,c i c i c i 1 此時c記錄小於等於i的元素的個數,c 1 2,c 2 2,c 3 3 d....

基礎演算法複習 快速排序

1.最近一直在忙課程,每天只能抽空刷幾道leetcode,好久沒看js了.有點慌,但是先抽空把排序演算法啥的寫一遍吧,等忙完作業系統課設再好好複習js.2.快速排序演算法思想大概就是設定乙個基準值,根據基準值不斷地交換陣列中前後的元素值,在此過程中目的是把基準值排序到最終的位置,再對基準值位置之前和...

內排序演算法

每次需要排序的時候總是會忘記基本的排序演算法,為了防止自己再次忘記,寫個部落格加深自己的印象 簡單選擇排序大概就是最簡單我們最容易想到的一種排序方法,一共進行n 1次選擇,在第i次選擇中選擇第i小的數放在相應的位置。我們可以想象一種場景,有一些賬單需要我們按照時間進行排序,我媽每次選擇最早的一張拿在...