定義
以數學式表示:
if
所估出來的函數式真正所需執行的上限。
Example:假如執行時間為
,求其時間複雜度為何?
Sol:
Find constantand :
when, , therefore the time complexity is
Big O | feature and explanation |
---|---|
constant time,執行時間為一個常數倍 | |
linear time,執行時間會隨資料大小而線性成長 | |
sub-linear time,成長速度較線性慢 | |
quadratic-time,執行時間會成二次方增長 | |
cubic-time,執行時間會成三次方增長 | |
exponential time,執行時間會成2的n次方增長 | |
線性乘對數時間,介於線性及二次方成長之間的行為 |
def bubbleSort(array):
for i in range(len(array)-1):
for j in range(0,len(array)-i-1):
if array[j]>array[j+1]:
#swap the element
array[j],array[j+1]=array[j+1],array[j]
return array
code:https://github.com/coherent17/algorithm/blob/main/sorting/bubblesort.py
#include <stdio.h>
#define SIZE 8
void bubbleSort(int *);
void printArray(int *);
int main(){
int data[SIZE]={16,25,39,27,12,8,45,63};
bubbleSort(data);
printArray(data);
return 0;
}
void bubbleSort(int *array){
void swap(int *, int *);
int i,j;
for(i=0;i<SIZE-1;i++){
for(j=0;j<SIZE-1-i;j++){
if (array[j]>array[j+1]){
swap(&array[j],&array[j+1]);
}
}
}
}
void swap(int *a, int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void printArray(int *array){
int i;
for(i=0;i<SIZE;i++){
printf("%d ",array[i]);
}
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/bubblesort.c
Bubble Sort的時間複雜度只有在給定的陣列為從小到大排序好的情形才會是
def Modified_bubbleSort(array):
for i in range(len(array)-1):
flag=True
for j in range(0,len(array)-i-1):
if array[j]>array[j+1]:
#swap the element and let flag become false
array[j],array[j+1]=array[j+1],array[j]
flag=False
if flag==True:
break
return array
code:https://github.com/coherent17/algorithm/blob/main/sorting/bubblesort.py
#include <stdio.h>
#define SIZE 8
void Modified_bubbleSort(int *);
void printArray(int *);
int main(){
int data[SIZE]={16,25,39,27,12,8,45,63};
Modified_bubbleSort(data);
printArray(data);
return 0;
}
void Modified_bubbleSort(int *array){
void swap(int *, int *);
int i,j,flag;
for(i=0;i<SIZE-1;i++){
flag=1;
for(j=0;j<SIZE-1-i;j++){
if(array[j]>array[j+1]){
swap(&array[j],&array[j+1]);
flag=0;
if(flag) break;
}
}
}
}
void swap(int *a, int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void printArray(int *array){
int i;
for(i=0;i<SIZE;i++){
printf("%d ",array[i]);
}
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/bubblesort.c
分成兩個步驟討論:
因此selection sort共需要
def selectionSort(array):
for i in range(len(array)-1):
#設未排序陣列中的第一個元素為最小的
min_index=i
for j in range(i+1,len(array)):
#找到未排序中最小元素的index
if array[min_index]>array[j]:
min_index=j
#將最小的數字放到已排序數列中的最後面
array[i],array[min_index]=array[min_index],array[i]
return array
code:https://github.com/coherent17/algorithm/blob/main/sorting/selection_sort.py
#include <stdio.h>
#define SIZE 8
void selectionSort(int *);
void printArray(int *);
int main(){
int data[SIZE]={16,25,39,27,12,8,45,63};
selectionSort(data);
printArray(data);
return 0;
}
void selectionSort(int *array){
void swap(int *,int *);
int i,j,min_index;
for(i=0;i<SIZE-1;i++){
//initiaize the index of the unsorted array
min_index=i;
//find the smallest nuber in the unsorted array
for(j=i+1;j<SIZE;j++){
if(array[min_index]>array[j]){
min_index=j;
}
}
//put the smallest number into the last of the sorted array
swap(&array[min_index],&array[i]);
}
}
void swap(int *a, int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void printArray(int *array){
int i;
for(i=0;i<SIZE;i++){
printf("%d ",array[i]);
}
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/selectionsort.c
def insertionSort(array):
for i in range(1,len(array)):
insert_num=array[i] #要插入的數字
j=i-1
while(j>=0 and insert_num<array[j]):
array[j+1]=array[j] #往右移
j-=1
array[j+1]=insert_num #插入新值
return array
code:https://github.com/coherent17/algorithm/blob/main/sorting/insertion_sort.py
#include <stdio.h>
#define SIZE 8
void insertionSort(int *);
void printArray(int *);
int main(){
int data[SIZE]={16,25,39,27,12,8,45,63};
insertionSort(data);
printArray(data);
return 0;
}
void insertionSort(int *array){
int i,j,insertion_num;
for(i=1;i<SIZE;i++){
//the number to insert
insertion_num=array[i];
j=i-1;
//shift the number right if the sorted array is bigger than the insertion number
while(j>=0&&insertion_num<array[j]){
array[j+1]=array[j];
j-=1;
}
//insert the number
array[j+1]=insertion_num;
}
}
void printArray(int *array){
int i;
for(i=0;i<SIZE;i++){
printf("%d ",array[i]);
}
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/insertionsort.c
說明:以
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
45 | 84 | 77 | 83 | 55 | 49 | 91 | 64 | 91 | 5 | 37 | 31 | 70 | 38 | 51 |
第一回合:
對
Example:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
84 | 77 | 83 | 55 | 91 | 64 | 91 | 5 | 31 | 70 | 38 | 51 |
排序後:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
84 | 77 | 83 | 55 | 91 | 64 | 91 | 5 | 31 | 70 | 38 | 51 |
對
對
對
對
經過上面
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
第二回合:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
可以看出顏色相同的數組已經被由小到大排序好了,此外,也可以看到較小的數字已經都在左側,而較大的數字也都已經移到右側了,已經變成一個快要完全排序完成的數列了,此時我們可以進行
第三回合:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
5 | 31 | 37 | 38 | 45 | 49 | 51 | 55 | 64 | 70 | 77 | 83 | 84 | 91 | 91 |
好懂的示意影片:
Learn More →
data=[45,84,77,83,55,49,91,64,91,5,37,31,70,38,51]
#define the gap by yourself
gap=[5,2,1]
def shell_sort(array,gap):
n=len(array)
#start gapped insertion sort
for current_gap in gap:
for i in range(current_gap,n):
#temp: the insertion number
temp=array[i]
j=i
#if the unsorted array is bigger than insertion number, then shift right
while j>=0 and j-current_gap>=0 and array[j-current_gap]>temp:
array[j]=array[j-current_gap]
j-=current_gap
#insert the insertion number
array[j]=temp
return array
code:https://github.com/coherent17/algorithm/blob/main/sorting/shell_sort.py
#include <stdio.h>
#define SIZE 15
void shellSort(int *, int *);
void printArray(int *);
int main(){
int data[SIZE]={45,84,77,83,55,49,91,64,91,5,37,31,70,38,51};
//define gap by yourself
int gap[3]={5,2,1};
shellSort(data,gap);
printArray(data);
return 0;
}
void shellSort(int *array, int *gap){
int i,j,k,current_gap,temp;
for(i=0;i<3;i++){
current_gap=gap[i];
for(j=current_gap;j<SIZE;j++){
temp=array[j];
k=j;
while(k>=0&&k-current_gap>=0&&array[k-current_gap]>temp){
array[k]=array[k-current_gap];
k-=current_gap;
}
array[k]=temp;
}
}
}
void swap(int *a, int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void printArray(int *array){
int i;
for(i=0;i<SIZE;i++){
printf("%d ",array[i]);
}
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/shellsort.c
在進入合併排序法前,我們先來看看分治法:把一個複雜的問題分成兩個或更多的相同或相似的子問題,直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。
在紙房子(一)第11集中,教授有預期警方會透過這種分治法去一一擊破夥伴們的心理,因此有事先想好應對的策略!
def merge_sort(array):
if len(array)>1:
#find the division point
mid=len(array)//2
left_array=array[:mid]
right_array=array[mid:]
#use recursion to keep dividing
merge_sort(left_array)
merge_sort(right_array)
#initialize the comparison index
right_index=0
left_index=0
merge_index=0
#start comparing
#case 1: right array compare with left array
while right_index<len(right_array) and left_index<len(left_array):
if right_array[right_index]<left_array[left_index]:
array[merge_index]=right_array[right_index]
right_index+=1
else:
array[merge_index]=left_array[left_index]
left_index+=1
merge_index+=1
#case 2: right array compare with itself
while right_index<len(right_array):
array[merge_index]=right_array[right_index]
right_index+=1
merge_index+=1
#case 3: left array compare with itself
while left_index<len(left_array):
array[merge_index]=left_array[left_index]
left_index+=1
merge_index+=1
return array
code:https://github.com/coherent17/algorithm/blob/main/sorting/merge_sort.py
#include <stdio.h>
#define SIZE 8
void mergeSort(int *, int *, int, int);
void printArray(int *);
int main(){
int data[SIZE]={5,3,8,6,2,7,1,4};
int reg[SIZE]={0};
mergeSort(data,reg,0,SIZE-1);
printArray(data);
return 0;
}
void mergeSort(int *array, int *reg, int front, int end){
int mid;
if(front<end){
mid=(front+end)/2;
//left sub-array:array[front,...,mid]
//right sub-array:array[mid+1,...,end]
mergeSort(array,reg,front,mid);
mergeSort(array,reg,mid+1,end);
//initialize the comparison pointer
int left_pointer=front;
int right_pointer=mid+1;
//loop counter
int i;
for(i=front;i<=end;i++){
//limit of the left pointer
if(left_pointer==mid+1){
reg[i]=array[right_pointer];
right_pointer+=1;
}
//limit of the right pointer
else if(right_pointer==end+1){
reg[i]=array[left_pointer];
left_pointer+=1;
}
//the element of the left sub-array is smaller than right sub-array
else if(array[left_pointer]<array[right_pointer]){
reg[i]=array[left_pointer];
left_pointer+=1;
}
//the element of the right sub-array is smaller than left sub-array
else{
reg[i]=array[right_pointer];
right_pointer+=1;
}
}
//copy the element from register to array
for(i=front;i<=end;i++){
array[i]=reg[i];
}
}
}
void printArray(int *array){
int i;
for(i=0;i<SIZE;i++){
printf("%d ",array[i]);
}
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/mergesort.c
Note:此處pivot的選擇為要排序陣列的最後一個元素
22 | 11 | 88 | 66 | 55 | 77 | 33 | 44 |
22 | 11 | 88 | 66 | 55 | 77 | 33 | 44 |
22 | 11 | 88 | 66 | 55 | 77 | 33 | 44 |
22 | 11 | 88 | 66 | 55 | 77 | 33 | 44 |
而後將陣列中
22 | 11 | 33 | 66 | 55 | 77 | 88 | 44 |
持續進行上面的步驟直到
(
22 | 11 | 33 | 66 | 55 | 77 | 88 | 44 |
而後將陣列中
22 | 11 | 33 | 55 | 77 | 88 | 66 |
---|
此時已經可以確定最開始時設定的pivot位置對於最終排序好的陣列是不會再改變了,而且在pivot左邊的子陣列中的元素都比它小,而pivot右邊的子陣列中的元素都比它大。未來僅需對pivot左邊的子陣列及右邊的子陣列同樣進行上述的步驟,便可以得到排序好的陣列!
對於左邊的子陣列持續進行上面同樣的步驟直到
(
22 | 11 | 33 | 55 | 77 | 88 | 66 | |
22 | 11 | 33 | 55 | 77 | 88 | 66 | |
而後將陣列中
22 | 11 | 55 | 77 | 88 | 66 |
---|
繼續對左邊的子陣列進行一樣的步驟:
22 | 11 | 55 | 77 | 88 | 66 | ||
此時可以發現
55 | 77 | 88 | 66 |
---|
我們就完成左半邊陣列的排序了,接著對陣列右半邊以同樣的步驟進行排序,最後變可以成功地得到已排序的陣列:
data=[22,11,88,66,55,77,33,44]
def quicksort(array,left,right):
if left<right:
partition_pos=partition(array,left,right)
quicksort(array,left,partition_pos-1)
quicksort(array,partition_pos+1,right)
def partition(array,left,right):
i=left
j=right-1
pivot=array[right]
while i<j:
#i move to right:
while i<right and array[i]<pivot:
i+=1
#j move to left:
while j>left and array[j]>pivot:
j-=1
#swap the element of index i and j
if i<j:
array[i],array[j]=array[j],array[i]
#swap the element of index i and p
if array[i]>pivot:
array[i],array[right]=array[right],array[i]
return i
quicksort(data,0,len(data)-1)
print(data)
code:https://github.com/coherent17/algorithm/blob/main/sorting/quicksort.py
#include <stdio.h>
#define SIZE 8
void swap(int *, int *);
int partition(int *, int, int);
void quickSort(int *, int, int);
void printArray(int *);
int main(){
int data[SIZE]={22,11,88,66,55,77,33,44};
quickSort(data,0,SIZE-1);
printArray(data);
return 0;
}
void quickSort(int *array, int left, int right){
if(left<right){
int partition_pos;
partition_pos=partition(array,left,right);
quickSort(array,left,partition_pos-1);
quickSort(array,partition_pos+1,right);
}
}
int partition(int *array, int left, int right){
int i,j,pivot;
i=left;
j=right;
pivot=array[right];
while(i<j){
//i move to right
while(i<right&&array[i]<pivot){
i++;
}
//j move to left
while(j>left&&array[j]>pivot){
j--;
}
//swap the element of the index i and j
if(i<j){
swap(&array[i],&array[j]);
}
}
//swap the element of the index i and p
if(array[i]>pivot){
swap(&array[i],&array[right]);
}
return i;
}
void swap(int *a, int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void printArray(int *array){
int i;
for(i=0;i<SIZE;i++){
printf("%d ",array[i]);
}
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/quicksort.c
以LSD(least significant digit)為例子:
給定義下陣列:
73 | 22 | 93 | 43 | 55 | 14 | 28 | 65 | 39 | 81 |
---|
Step 1:
在經過這些數值時,依據個位數的大小將其分配到0~9的桶子內,並遵守下面的規則:
按照以上規則,將陣列的所有數值依據個位數排序好之後可以獲得:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
81 | 65 | 39 | |||||||
43 | 14 | 55 | 28 | ||||||
93 | |||||||||
22 | 73 |
Step 2:
將剛剛依據個位數放進桶子的數值串接起來,並遵守下面的規則:
由以上規則,我們所得到的陣列為:
81 | 22 | 73 | 93 | 43 | 14 | 55 | 65 | 28 | 39 |
---|
Step 3:
重複Step 1,不過改成對十位數進行分配:
按照以上規則,將陣列的所有數值依據十位數排序好之後可以獲得:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
28 | 39 | ||||||||
14 | 22 | 43 | 55 | 65 | 73 | 81 | 93 |
Step 4:
重複Step 2,將其串接在一起,便完成了排序:
14 | 22 | 28 | 39 | 43 | 55 | 65 | 73 | 81 | 93 |
---|
要進行幾次的分配及串接是取決於這些數值中最大位數的那個數字有幾位。
LSD的radix sort適用於位數較少的數列,然而在運算數值較大的陣列則是MSD的radix sort效率會比較高。
定義
def getMax(array):
max=array[0]
for i in range(1,len(data)):
if array[i]>max:
max=array[i]
return max
def radixSort(array):
temp_array=[0]*len(array)
significantDigit=1
largestNum=getMax(array)
while largestNum/significantDigit>0:
bucket=[0]*10
# count how many number put into each bucket
for i in range(len(array)):
bucket[int(array[i]/significantDigit)%10]+=1
# use prefix sum to determine where to put the number
for i in range(1,9+1):
bucket[i]+=bucket[i-1]
for i in range(len(array)-1,-1,-1):
digitNumber=int(array[i]/significantDigit)%10
# need to -1 because the prefix sum include itself
bucket[digitNumber]-=1
temp_array[bucket[digitNumber]]=array[i]
# copy the array
for i in range(len(array)):
array[i]=temp_array[i]
significantDigit*=10
return array
code:https://github.com/coherent17/algorithm/blob/main/sorting/radixort.py
#include <stdio.h>
#define SIZE 8
int getMax(int *);
void radixSort(int *);
void printArray(int *);
int main(){
int data[SIZE]={170,45,75,90,802,24,2,66};
radixSort(data);
printArray(data);
return 0;
}
int getMax(int *array){
int max,i;
max=array[0];
for(i=1;i<SIZE;i++){
if(array[i]>max){
max=array[i];
}
}
return max;
}
void radixSort(int *array){
int i;
int temp_array[SIZE];
int significantDigit=1;
int largestNum=getMax(array);
while(largestNum/significantDigit>0){
int bucket[10]={0};
//count how many number put into each bucket
for(i=0;i<SIZE;i++){
bucket[(array[i]/significantDigit)%10]++;
}
//use prefix sum to determine where to put the number
for(i=1;i<10;i++){
bucket[i]+=bucket[i-1];
}
for(i=SIZE-1;i>=0;i--){
int digitNumber=(array[i]/significantDigit)%10;
//need to -1 because the prefix sum include itself
temp_array[--bucket[digitNumber]]=array[i];
}
//copy the array
for(i=0;i<SIZE;i++){
array[i]=temp_array[i];
}
//move to the next significantDigit number
significantDigit*=10;
}
}
void printArray(int *array){
int i;
for(i=0;i<SIZE;i++){
printf("%d ",array[i]);
}
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/radixsort.c
在了解堆積排序法前,需要先知道:
0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
3 | 9 | 2 | 1 | 4 | 5 |
#include <stdio.h>
void swap(int *, int *);
void heapify(int *, int, int);
void insert(int *, int);
void delete(int *, int);
void printArray(int *, int);
//global variable
int size=0;
int main(){
int array[10];
insert(array,3);
insert(array,4);
insert(array,9);
insert(array,5);
insert(array,2);
printArray(array,size);
delete(array,9);
printArray(array,size);
return 0;
}
void swap(int *a, int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void heapify(int *array, int size, int i){
int largest=i;
int left_children=2*i+1;
int right_children=2*i+2;
if(left_children<size && array[left_children]>array[largest]) largest=left_children;
if(right_children<size && array[right_children]>array[largest]) largest=right_children;
//check need to swap or not?
if(largest!=i){
swap(&array[i],&array[largest]);
heapify(array,size,largest);
}
}
void insert(int *array, int newNumber){
array[size]=newNumber;
size+=1;
//loop to heapify
int i;
for(i=size/2-1;i>=0;i--){
//i is the index of the parent node
heapify(array, size, i);
}
}
void delete(int *array, int delNumber){
//find the index of the number to delete
int i;
for(i=0;i<size;i++){
if(array[i]==delNumber) break;
}
//swap to the end of the binary tree
swap(&array[i],&array[size-1]);
size-=1;
//loop to heapify
for(i=size/2-1;i>=0;i--){
heapify(array, size, i);
}
}
void printArray(int *array,int size){
int i;
for(i=0;i<size;i++){
printf("%d ",array[i]);
}
printf("\n");
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/max_heap_data_structure.c
那要如何透過堆積的排序數列呢?我們可以將每次heapify後的binary tree的最大值(根部root),將其與樹的末端交換,也就是將其放到陣列的最後一個位置,之後刪除其在binary tree中的位置,再繼續進行相同的動作便可以將此數列排序完畢。
def heapify(array,size,i):
largest=i
left_children=2*i+1
right_children=2*i+2
if left_children<size and array[left_children]>array[largest]:
largest=left_children
if right_children<size and array[right_children]>array[largest]:
largest=right_children
# //check need to swap or not?
if largest!=i:
array[i],array[largest]=array[largest],array[i]
heapify(array,size,largest)
def heapSort(array):
# construct max heap:
n=len(array)
for i in range(n//2,-1,-1):
heapify(array,n,i)
# swap the root(index=0) to the end of the array and delete it
for i in range(n-1,0,-1):
array[i],array[0]=array[0],array[i]
#heapify root element:
heapify(array,i,0)
code:https://github.com/coherent17/algorithm/blob/main/sorting/heapsort.py
#include <stdio.h>
#define SIZE 8
void swap(int *, int *);
void heapify(int *, int, int);
void heapSort(int *, int);
void printArray(int *);
int main(){
int data[SIZE]={16,25,39,27,12,8,45,63};
heapSort(data,SIZE);
printArray(data);
return 0;
}
void swap(int *a, int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void heapify(int *array, int size, int i){
int largest=i;
int left_children=2*i+1;
int right_children=2*i+2;
if(left_children<size && array[left_children]>array[largest]) largest=left_children;
if(right_children<size && array[right_children]>array[largest]) largest=right_children;
//check need to swap or not?
if(largest!=i){
swap(&array[i],&array[largest]);
heapify(array,size,largest);
}
}
void heapSort(int *array, int size){
//construct max heap:
int i;
for(i=size/2-1;i>=0;i--){
heapify(array, size, i);
}
//swap the root(index=0) to the end of the array and delete it
for(i=size-1;i>=0;i--){
swap(&array[0],&array[i]);
//heapify again to get the maxheap
heapify(array,i,0);
}
}
void printArray(int *array){
int i;
for(i=0;i<SIZE;i++){
printf("%d ",array[i]);
}
printf("\n");
}
code:https://github.com/coherent17/algorithm/blob/main/sorting/heapsort.c