算法基礎(chǔ)
- 遞歸算法的空間復(fù)雜度 = 每次遞歸的空間復(fù)雜度 * 遞歸深度
- c/c++的內(nèi)存管理
- 固定部分:
- 代碼區(qū):存放二進(jìn)制代碼
- 數(shù)據(jù)區(qū):全局變量,靜態(tài)變量和常量等等
- 可以變部分
- 棧區(qū):運(yùn)行方法的形參,局部變量,返回值,以及遞歸棧所需的空間.系統(tǒng)自動(dòng)分配和回收
- 堆區(qū):動(dòng)態(tài)開辟的空間,存放new出來的對象在堆區(qū)中的真實(shí)數(shù)據(jù).需要手動(dòng)回收
- 固定部分:
- 內(nèi)存對齊:
- 平臺(tái)原因:為了同一個(gè)程序可以在多平臺(tái)運(yùn)行,需要內(nèi)存對齊
- 硬件原因:經(jīng)過內(nèi)存對齊后,CPU訪問內(nèi)存的速度大大提升
- 內(nèi)存對齊:一次尋址即可. 非內(nèi)存對齊:兩次尋址+一次合并操作
- 數(shù)組是存放在連續(xù)內(nèi)存空間上的相同類型數(shù)據(jù)的集合,刪除/添加元素要移動(dòng)其他元素
- 有序不唯一元素是二分法的前提條件
- 算法特征:
- 明確性:算法應(yīng)該清晰明確.每個(gè)步驟及其輸入/輸出明確并只能產(chǎn)生一種含義
- 輸入:應(yīng)該有0個(gè)或以上定義明確的輸入
- 輸出:應(yīng)該有1個(gè)或以上明確定義和匹配所需的輸出
- 有限性:必須在有限步驟后終止
- 可行性:在可用資源下是可行的
- 獨(dú)立性:有分步知道,獨(dú)立于任何編程代碼
- 貪婪算法:
- 貪心算法試圖找到局部最優(yōu)解,這可能最終導(dǎo)致全局優(yōu)化解。然而,一般貪婪算法不提供全局優(yōu)化的解決方案。
- 實(shí)例:
- 動(dòng)態(tài)規(guī)劃之TSP(Travel Salesman Problem)算法:https://blog.csdn.net/diaosi1446427351/article/details/80384279
- 最小生成樹算法(普里姆算法 Prim`s algorithm) https://blog.csdn.net/feliciafay/article/details/19150519
- Kruskal’s Minimum Spanning Tree Algorithm 最小生成樹 https://www.cnblogs.com/mqxnongmin/p/10542681.html
- 最短路徑算法之Dijkstra's Minimal Spanning Tree Algorithm https://blog.csdn.net/qq_42370259/article/details/81981857
- Graph - Map Coloring https://www.includehelp.com/algorithms/graph-coloring-problem-solution-using-backtracking-algorithm.aspx
- Graph - Vertex Cover 無向圖計(jì)算——最小頂點(diǎn)覆蓋 https://blog.csdn.net/qq_39825375/article/details/103132112
- 背包問題(Knapsack Problem)https://blog.csdn.net/weixin_40756041/article/details/88053823
- Job Scheduling Problem作業(yè)車間調(diào)度問題 https://blog.csdn.net/Jayphone17/article/details/103434555
- 分治算法:
- 1.劃分;2.解決;3.合并
- 實(shí)例:
- Merge sort(歸并排序) https://blog.csdn.net/a130737/article/details/38228369
- Quick Sort(快速排序) https://www.cnblogs.com/lingnan/p/4900297.html
- Binary Search(二分法查找) https://www.cnblogs.com/wkfvawl/p/9475939.html
- Strassen's Matrix Multiplication(矩陣相乘算法)
- Closest pair (points) 最近點(diǎn)對問題 https://blog.csdn.net/u013522065/article/details/44810915
- 動(dòng)態(tài)規(guī)劃:
- 類似于分治法,將問題分解為更小的可能的子問題。這些較小子問題的結(jié)果會(huì)被記住并用于相似或重疊的子問題
- 實(shí)例:
- Fibonacci number series(斐波那契數(shù)列) https://www.cnblogs.com/garrettlu/p/10064932.html
- 背包問題(Knapsack Problem)
- Tower of Hanoi(漢諾塔問題) https://blog.csdn.net/qq_39980334/article/details/104276562
- All pair shortest path by Floyd-Warshall http://alrightchiu.github.io/SecondRound/all-pairs-shortest-pathfloyd-warshall-algorithm.html
- 最短路徑(Shortest Path)- Dijkstra(迪杰斯特拉算法) https://blog.csdn.net/songzhuo1991/article/details/103072113
- Project scheduling(進(jìn)程調(diào)度算法) https://blog.csdn.net/qq_45913057/article/details/109690121
- 派生數(shù)據(jù)類型:List, Array, Stack, Queue
- 基本操作:Traversing(遍歷),Searching,Insertion, Deletion, Sorting, Merging
- 數(shù)組:
- 鏈表:鏈表是一系列數(shù)據(jù)結(jié)構(gòu),它們通過鏈接連接在一起。
- 單向鏈表:
- 鏈接:鏈表的每個(gè)鏈接都可以存儲(chǔ)稱為元素的數(shù)據(jù)。
- 鏈表的每個(gè)鏈接都包含一個(gè)鏈接到名為 Next 的下一個(gè)鏈接。
- 鏈表包含到第一個(gè)名為 First 的鏈接的連接鏈接。
- 雙向鏈表(Doubly Linked List):
- 比單向鏈表多一個(gè)Prev
- 操作:插入開始,刪除開始,插入最后,刪除最后,后插入,根據(jù)key刪除,正向顯示,向后顯示
- 循環(huán)鏈表:最后一個(gè)元素指向第一個(gè)元素
- 操作:插入,刪除,顯示
- 單向鏈表:
- 堆棧:堆棧是一種抽象數(shù)據(jù)類型 (ADT),通常用于大多數(shù)編程語言。
- 操作:push,pop, peek, isFull, isEmpty
- 隊(duì)列:Queue 是一種抽象的數(shù)據(jù)結(jié)構(gòu),FIFO
- 操作:enqueue, dequeue,peek,isfull, isempty
- 查找:
- 線性搜索是一種非常簡單的搜索算法
- 二分查找(Binary search):必須對目標(biāo)數(shù)組進(jìn)行排序
- 步驟:
- 1.找出中位數(shù) mid
- 2.目標(biāo)target 與mid比較
- 3.對比成功或者查無此目標(biāo)
- 步驟:
- 插值搜索(Interpolation search):此搜索算法適用于所需值的探測位置
- mid = Lo + ((Hi - Lo) / (A[Hi] - A[Lo])) * (T - A[Lo])
- 步驟:步驟跟二分查找一樣
- 哈希表是一種以關(guān)聯(lián)方式存儲(chǔ)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),在哈希表中,數(shù)據(jù)以數(shù)組格式存儲(chǔ),其中每個(gè)數(shù)據(jù)值都有自己唯一的索引值
- 插入和搜索操作都非??斓臄?shù)據(jù)結(jié)構(gòu)
- 散列是一種將一系列鍵值轉(zhuǎn)換為數(shù)組索引范圍的技術(shù) hash:12 % 20 = 12
- 通過查看下一個(gè)單元格來搜索數(shù)組中的下一個(gè)空位置,直到找到一個(gè)空單元格。這種技術(shù)稱為線性探測。
- 排序算法:
- 冒泡排序(Bubble sort) Ο(n^2)
- 插入排序:(Insertion sort) Ο(n^2)
- 1.每兩個(gè)比較一次
- 2.每比較完一次都有對所有已比較過的都比較一次
- 選擇排序:將列表分為兩部分,左端的已排序部分和右端的未排序部分 Ο(n^2)
- 1.選擇最小的放在最左邊
- 歸并排序:一種基于分治技術(shù)的排序技術(shù) Ο(n log n)
- 1.分成單個(gè)元素
- 2.對比合并
- 希爾排序(Shell sort): 最好情況 O(n)
- 如果較小的值在最右側(cè)并且必須移到最左側(cè),則該算法避免了在插入排序的情況下的大移位
- 1.h = h * 3 + 1
- 2.將列表劃分為等間隔 h 的較小子列表
- 3.使用插入排序?qū)@些子列表進(jìn)行排序
- 快速排序是一種高效的排序算法,它基于將數(shù)據(jù)數(shù)組劃分為更小的數(shù)組
- 步驟1:
- 1.選擇最高的索引值pv
- 2.取最左lo和最右hi不包括pv
- 3.lo小于pv,右移; 右值大于pv,左移
- 4.如果第三步都為FALSE,交換lo和hi
- 5.如果lo>=hi,則交換lo和pv;重復(fù)
- 步驟2:(遞歸)
- 1.最右邊的索引值pv
- 2.以pv分組
- 3.遞歸快速排序左分區(qū)
- 4.遞歸快速排序右分區(qū)
- 步驟1:
- 圖:是一組對象的圖形表示,其中一些對象對通過鏈接連接(頂點(diǎn)(Vertex),邊(Edge),相鄰(Adjacency),路徑(path))
- 深度優(yōu)先搜索(Depth First Search (DFS)):以深度運(yùn)動(dòng)方式遍歷圖,并使用堆棧來記住在任何迭代中出現(xiàn)死胡同時(shí)獲取下一個(gè)頂點(diǎn)以開始搜索。
- 1.初始化棧
- 2.第一個(gè)頂點(diǎn)壓入棧,第二個(gè)..回到第一個(gè)頂點(diǎn)停止
- 3.出棧并檢查是否有未訪問節(jié)點(diǎn),有的話執(zhí)行步驟2
- 重復(fù)123,直到全部出棧
- 廣度優(yōu)先搜索 (BFS) 算法以廣度運(yùn)動(dòng)遍歷圖,并使用隊(duì)列記住在任何迭代中出現(xiàn)死胡同時(shí)獲取下一個(gè)頂點(diǎn)以開始搜索。
- 1.初始化隊(duì)列
- 2.標(biāo)記起始點(diǎn)S,S相鄰未訪問的點(diǎn)添加到隊(duì)列(FIFO)
- 3.第一個(gè)入隊(duì)的點(diǎn),移出并檢查未訪問點(diǎn),將其入隊(duì),重復(fù)執(zhí)行步驟2
- 4.重復(fù)123,直到全部出隊(duì)
- 深度優(yōu)先搜索(Depth First Search (DFS)):以深度運(yùn)動(dòng)方式遍歷圖,并使用堆棧來記住在任何迭代中出現(xiàn)死胡同時(shí)獲取下一個(gè)頂點(diǎn)以開始搜索。
- 樹:(Path,Root,Parent,Child,Leaf,Subtree,Visiting,Traversing,Levels,Keys)
- 遍歷樹:
- 有序遍歷(In-order Traversal)
- 遞歸左邊子樹(左下->中上->右下)
- 根節(jié)點(diǎn)
- 遞歸右邊子樹(左下->中上->右下)
- 前序遍歷(Pre-order Traversal)
- 根節(jié)點(diǎn)
- 遞歸左邊子樹(中上->左下->右下)
- 遞歸右邊子樹(中上->左下->右下)
- 后序遍歷(Post-order Traversal)
- 遞歸左邊子樹(左下->右下->中上)
- 遞歸右邊邊子樹(左下->右下->中上)
- 根節(jié)點(diǎn)
- 有序遍歷(In-order Traversal)
- 二叉搜索樹(BST):
- 特性:
- 左子樹的鍵值小于其父(根)節(jié)點(diǎn)的鍵值。
- 右子樹的鍵值大于或等于其父(根)節(jié)點(diǎn)的鍵值。
- 操作:
- 遍歷樹
- 查找
- 插入
- 特性:
- [平衡]AVL二叉樹(AVL Trees):BalanceFactor = height(left-sutree) ? height(right-sutree)
- 左旋轉(zhuǎn):節(jié)點(diǎn)插入到右子樹,執(zhí)行左旋轉(zhuǎn)
- 右下B與中上A旋轉(zhuǎn)調(diào)整為左下A和B,左下B與左下C旋轉(zhuǎn)調(diào)整為中上B和右下C
- 右旋轉(zhuǎn):節(jié)點(diǎn)插入到左子樹,執(zhí)行右旋轉(zhuǎn)
- 左下B與中上C旋轉(zhuǎn)調(diào)整為右下B和C,右下B與右下C旋轉(zhuǎn)調(diào)整為中上B和左下C
- 左旋轉(zhuǎn):節(jié)點(diǎn)插入到右子樹,執(zhí)行左旋轉(zhuǎn)
- 生成樹是圖 G 的一個(gè)子集,它的所有頂點(diǎn)都被盡可能少的邊數(shù)覆蓋。因此,生成樹沒有環(huán),也不能斷開。
- 一個(gè)無向圖最多有n^(n-2)個(gè)生成樹
- 從生成樹中刪除一條邊將使圖斷開連接,即生成樹是最小連接的。
- 向生成樹添加一條邊將創(chuàng)建一個(gè)回路或環(huán)路,即生成樹最大程度地是非循環(huán)的。
- 應(yīng)用:
- 民用網(wǎng)絡(luò)規(guī)劃
- 計(jì)算機(jī)網(wǎng)絡(luò)路由協(xié)議
- 聚類分析
- 堆是平衡二叉樹數(shù)據(jù)結(jié)構(gòu)的一種特殊情況,其中根節(jié)點(diǎn)鍵與其子節(jié)點(diǎn)進(jìn)行比較并相應(yīng)地排列
- Min-Heap - 根節(jié)點(diǎn)的值小于或等于其任一子節(jié)點(diǎn)。
- Max-Heap - 根節(jié)點(diǎn)的值大于或等于其任一子節(jié)點(diǎn)。
- 最大堆構(gòu)建算法:
- 1.在堆的末尾創(chuàng)建一個(gè)新節(jié)點(diǎn)。
- 2.為節(jié)點(diǎn)分配新值。
- 3.將此子節(jié)點(diǎn)的值與其父節(jié)點(diǎn)的值進(jìn)行比較。
- 4.如果父值小于子值,則交換它們。
- 5.重復(fù)第 3 步和第 4 步,直到 Heap 屬性成立。
- 最小生成樹算法:
- Prim 尋找最小成本生成樹的算法(如 Kruskal 算法)使用貪婪方法。 Prim 算法與最短路徑優(yōu)先算法有相似之處。
- Kruskal 尋找最小成本生成樹的算法使用貪婪方法。該算法將圖視為森林,并將其擁有的每個(gè)節(jié)點(diǎn)視為一棵樹。一棵樹僅連接到另一個(gè)樹,并且僅當(dāng)它在所有可用選項(xiàng)中成本最低且不違反 MST 屬性。
- 遍歷樹:
數(shù)據(jù)結(jié)構(gòu)與操作
鏈表
- 單向鏈表
- 結(jié)構(gòu):
struct node{ int data; int key; struct node *next; }- 操作:
- while(ptr!=NULL){ptr = ptr->next}
- insertFirst(){*link = (struct node*) malloc(sizeof(struct node));head = link;}
- deleFirst(){head=head->next}
- isEmpty(){return head==NULL}
- length(){while(!current){length++;current=current->next}}
- find(){while(current->key != key){return current}}
- deleteByKey(){previous->next=current->next}
- sort(){}
- reverse(){}
算法步驟
- 二分法步驟
- 初始化 left=0,right=size-1,middle=left+(right-left)/2
- 不斷縮小left到right的范圍,找到target
- 雙指針1(移除元素):
- 初始化slowIndex=0,fastIndex=0
- 如果[fastIndex]!=target,[slowIndex++]=[fastIndex]
- 雙指針2(有序數(shù)組的平方):
- 初始化lowestIndex=0,highestIndex=size-1
- 滑動(dòng)窗口(長度最小數(shù)組之和>=target)
- 初始化slowIndex=0,fastIndex=0
- 如果slowIndex到fastIndex之和大于等于target,slowIndex前移
- 鏈表
- 刪除D節(jié)點(diǎn):C->next = D->next;free(D)
- 添加F節(jié)點(diǎn):C->next=F;F->next=D;
- 刪除鏈表元素
- 刪除頭結(jié)點(diǎn)
- 新建tmp=head;
- head = head->next;(向前移一位)
- delete tmp;
- 刪除非頭部節(jié)點(diǎn)
- 新建cur=head;
- 新建tmp = cur->next;(刪除非頭部+1.得出)
- cur->next=cur->next->next;
- delete tmp;
- 刪除頭結(jié)點(diǎn)
- 翻轉(zhuǎn)鏈表
- 定義一個(gè)cur=head,pre=null
- tmp=cur->next;cur->next = pre;
- pre=cur; cur = tmp;
- 鏈表相交
- 兩鏈表的end()對齊
- 找出curA==curB
- 環(huán)形鏈表
- 哈希表(Hash table):一般用來快速判斷一個(gè)元素是否出現(xiàn)在集合里
- 棧和隊(duì)列
- 二叉樹(binary tree)
- 滿二叉樹:深度為k,有2^k-1個(gè)節(jié)點(diǎn)的二叉樹
- 完全二叉樹:允許右葉子缺失的滿二叉樹
- 二叉樹遍歷:
- 中序遍歷:cur=root;cur.left==NULL ? stack.push(cur):cur=cur.left;
- 前序遍歷:stack.push(root);cur=stack.pop();stack.push(cur.left);stack.push(cur.right)
- 后序遍歷:用兩個(gè)棧
- 層序遍歷(圖論中的廣度優(yōu)先遍歷):
- que.push(root);node = que.front();que.pop();que.push(node.left);que.push(node.right);
- 回溯算法
- 理論基礎(chǔ)
- 組合,分割,子集,排列,棋盤問題,其他.
- 回溯算法是一種搜索方式.有遞歸就有回溯
- 組合
- 理論基礎(chǔ)