資料結構中的演算法,指的時資料結構所具備的功能
解決特定問題的方法,它是前輩的一些優秀的經驗總結
有窮性(finiteness):演算法的有窮性是指演算法必須能在執行bai有限個步驟之後終止;
確切性(definiteness):演算法的每一步驟必須有確切的定義;
輸入項(input):乙個演算法有0個或多個輸入,以刻畫運算物件的初始情況,所謂0個輸入是指演算法本身定出了初始條件;
輸出項(output):乙個演算法有乙個或多個輸出,以反映對輸入資料加工後的結果。沒有輸出的演算法是毫無意義的;
可行性(effectiveness):演算法中執行的任何計算步驟都是可以被分解為基本的可執行的操作步,即每個計算步都可以在有限時間內完成(也稱之為有效性)。
時間複雜度:由於計算機的效能不同,無法準確的統計出乙個演算法執行所需要的時間。
因此我們用演算法執行的次數來代表演算法的時間複雜度
o(公式)
// o(1)
printf
("%d");
// o(n)
for(
int i=
0; i)// o(logn)
for(
int i=n;i>=
0;i/=2
)// o(nlogn)
for(
int i=
0;i// o(n^2)
for(
int i=
0;i)}
把乙個大而複雜的問題,分解成很多小而簡單的問題,利用計算機強大的計算能力來解決問題
實現分治的方法:迴圈、遞迴
對待查詢的資料沒有任何要求,從頭到尾逐一查詢,適合小規模的資料查詢中常見,但是相對效率低,
待查詢的資料必須是有序的,從資料的中間位置查詢,如果中間的值比key小,則繼續往右邊進行二分查詢,如果比key大,則往左邊進行二分查詢
是一種對資料進行處理的思想,不是一種特定的演算法,當資料量很多時,可以對資料進行分塊處理,然後再進行查詢,例如英語詞典。
排序演算法的穩定性:
在待排序的資料中,如果有值相同的資料,在排序的過程中如果不會改變他們的相對順序,則認為該排序演算法為穩定的。
對於資料左右進行比較,把最大的交換到最後,特點:該演算法對資料的有序性敏感,在排序的過程中發現有序可以立即停止,如果待排序的資料基本有序,則氣泡排序的效率是非常高的。
時間複雜度平均:o(n^2) 最優:o(n)
穩定性穩定
#define swap(a,b)
// 氣泡排序
void
bubble_sort
(int
* arr,size_t len)}}
}
假設最開始的位置是最小值的下標並記錄該下標為min,然後與後面的資料比較,如果有比min位置的資料小的,則更新min為更小的資料的下標,最後如果最後min的值發生了變化,則交換min位置的資料與最開始位置的資料,雖然時間複雜度較高,資料交換的次數較少,因此實際執行的速度並不慢
但是資料交換的次數比較少,因此實際執行的速度並不慢
選擇排序是氣泡排序的乙個變種,但是對資料的有序性不敏感
資料基本有序時冒泡快,時間混亂時選擇快
時間複雜度o(n^2)
穩定性不穩定的 10 10 1
void
select_sort
(int
* arr,size_t len)
if(min != i)
swap
(arr[min]
,arr[i]);
}}
把資料看成兩部分,一部分是有序的,剩餘的資料逐個插入進去,當資料全部插入完成後,整個資料就是有序的。
適合對已排序好的資料,新增資料並排序。
對資料不敏感
時間複雜度o(n^2)
穩定性穩定的
void
insert_sort
(int
* arr,size_t len)
if(j != i) arr[j]
= val;
}show_arr
(arr)
;printf
("%s\n"
,__func__);
}
實現:找到乙個標桿,一方面從左邊找比標桿值大的資料,找到後放在標桿的右邊,另一方面從右邊找比標桿值小的資料,找後放在標桿的左邊,最終標桿左邊的資料都比它小,右邊的資料都比它大,這樣整體有序,然後按照同樣的方式排序標桿左右兩邊的資料。
它的綜合性能高,因此叫快速排序,筆試考的最多
時間複雜度o(nlogn)
穩定性不穩定
//快速排序依賴
void
_quick_sort
(int
* arr,
int left,
int right)
// 在標桿右邊找比pv小的資料
while
(r>pi && arr[r]
>=pv) r--;if
(r > pi)
}// 還原標桿
arr[pi]
= pv;
// 如果左邊資料不少於兩個,繼續快排
if(pi-left >1)
_quick_sort
(arr,left,pi-1)
;// 如果右邊資料不少於兩個,繼續快排
if(right-pi >1)
_quick_sort
(arr,pi+
1,right);}
// 快速排序
void
quick_sort
(int
* arr,size_t len)
先把一組資料拆分成單獨的個體,然後以從小到大的順序進行合併,由於需要使用額外的記憶體空間因此
避免了資料的交換的耗時,也是一種典型的以空間換時間的演算法
時間複雜度o(logn)
穩定性穩定的
// 歸併依賴2 合併
void
merge
(int
* arr,
int* tmp,
int l,
int p,
int r)
// 任意一部分放入結束後,把另外一部份剩餘的放入tmp末尾
while
(i<=p) tmp[k++
]= arr[i++];
while
(j<=r) tmp[k++
]= arr[j++];
// 把tmp合併排序好後的資料重新賦值給arr對應的位置
while
(l<=r) arr[l]
= tmp[l++];
}// 歸併排序依賴1 拆分
void
_merge_sort
(int
* arr,
int* tmp,
int l,
int r)
// 歸併排序
void
merge_sort
(int
* arr,size_t len)
把資料當做完全二叉樹,然後在樹中調整為大根樹,然後把根節點交換到末尾,然後數量–,接下去繼續調整為大根樹,直到節點數量為1時結束,結束後該資料
時間複雜度o(logn)
穩定性不穩定
// 構建堆結構
void
create_heap
(int
* arr,
int root,size_t len)
// 堆排序
void
heap_sort
(int
* arr,size_t len)
show_arr
(arr,len)
;printf
("%s\n"
,__func__);
}
常用的 查詢演算法與排序演算法
順序查詢 從列表第乙個元素開始,順序進行搜尋,直到找到為止。二分查詢 從有序列表的候選區data 0 n 開始,通過對待查詢的值與候選區中間值的比較,可以使候選區減少一半。li 1,2,3,4,5,6,7,8,9 val 5 defsearch li,val low 0 high len li 1 ...
各種排序與查詢演算法
include include include define swap a,b intorder find int arr,size t len,int key return 1 int binary find int arr,size t l,size t r,int key intbinary ...
簡單的排序演算法
排序演算法 需要排序的陣列 let nums 5,1 2,3 4 6,9,7,10,8 let nums 1,6,5 class sortclass quicksort 找出乙個基準值a,把比a小的放入左邊,比a大的放入右邊 可以隨機獲得a 平均時間複雜度為 o nlogn param left p...