作為一個iOS開發小白,數據結構是必須的,在各種詢問求助后,了解到這本書海可以,比較適合自己:也做一些筆記,方便日后查詢。
本文章筆記為方便個人使用,主要記錄一些基礎概念,主要方便之后學習算法導論查看一下概念(數據結構里概念太繁雜)有興趣碼友可以看看。
1 基礎
數據結構:是相符之間存在一種或多種特定關系到數據元素的集合。
1.1 邏輯結構: 數據對象中數據元素之間的相互關系
1.1.1 集合結構:集合結構的數據元素除同屬於一個集合外,它們之間沒有其他的關系;
1.1.2 線性結構:數據元素之間是一一對應的;
1.1.3 樹形結構:數據元素之間存在一種一對多多層次關系;
1.1.4 圖形結構:數據元素是多對多多關系;
1.2 物理結構:數據的邏輯結構在計算機中的存儲形勢
1.2.1 順序存儲結構:把數據元素存放在地址連續的存儲單元里,其邏輯關系和物理關系一致(數組);
1.2.2 鏈式存儲結構:數據元素存放在任意的存儲單元里,這組存儲單元可以聯系也可不連續;
1.3 抽象數據類型
數據類型:一組性質相同的值的集合及定義在此集合上的一些操作的總稱
類型就是用來說明變量或表達式的取值范圍和所能進行的操作
抽象:取出事物具有普遍性的本質;
1.3.1 抽象數據類型:指一個數學模型及定義在該模型上的一組操作;
2 算法
是解決特定問題求解步驟等描述,在計算機中表現為指令等有限序列,並且每條指令表示一個或多個操作;
特性:輸入輸出,
有窮性:執行有限步驟之后,自動結束而不會出現無限循環,並且每一個步驟在可接受的時間內完成;
確定性:算法的每一步驟具有確定的含義,不會出現二意性;
可行性:算法的每一步都必須可行,每一步都能夠通過執行有限次數完成;
正確性,可讀性, 健壯性:對不合法的輸入做出相關處理;
時間效率高,存儲量低;
2.7 算法效率的度量方法
事前分析估算方法:在計算機程序編制前,依據統計方法對算法進行估算;
函數的漸進增長:給定兩個函數f(n)和g(n),如果存在一個整數N,使得對於n>N,f(n)和總比g(n)大,那么,我們說f(n)的增長漸進快於g(n)
2.8 算法時間復雜度
:語句總的執行次數T(n)是關於問題規模n的函數,進而分析T(n)隨n變化的情況並確定T(n)的數量級。算法的時間亮度,記作:T(n)=O(f(n))。它表示隨着問題規模n的增大,算法執行時間的增長率和f(n)的增長率相同,稱作算法的漸進時間復雜度,簡稱時間復雜度。集中f(n)是問題規模n的某個函數。
O(1) < O(lgn) < O(n) < O(nlgn) < O(n2)< O(n3)<O(2n) < O(n!) < O(nn)
2.12 算法的空間復雜度
S(n)=O(f(n)):n為問題規模,f(n)為語句關於n所占存儲空間的函數;
3 線性表
線性表元素個數定義為線性表長度,n=0,為空表;
線性表的順序存儲結構:用一段地址連續的存儲單元依次存儲線性表的數據元素(一維數組)
3.4.3 數組長度:存儲空間的長度; 線性表的長度:線性表中數據元素的個數;
存儲器中的每個單元都有自己的編號,稱為地址;
Loc(ai)=Loc(a1) +(i-1)*c 時間復雜度:存取時間性能O(1) ---隨機存儲結構
3.5.4 優點:無須為邏輯關系增加額外存儲空間,可以快速存取表中任意位置;
缺點:插入刪除需移動大量元素,線性表長度變化難以確定存儲空間,存儲空間“碎片”
3.6 線性表的鏈式存儲結構
一個節點:數據(數據域)+指針(指針域)
單鏈表:每個結點只包含一個指針域
頭指針:鏈表中第一個結點的存儲位置; 線性鏈表的最后一個結點指針為空(NULL)
頭結點:單鏈表的第一個結點前設的一個結點;數據域一般無意義(可存儲鏈表長度)
頭指針不為空;頭結點不一定是鏈表必須要素
3.8.1 單鏈表的插入,將s插入到p后: s->next=p->next, p->next=s(賦值順序不能調換,否則出錯)
3.9 單鏈表整表創建:r->next=p(將新建p結點放在r后面),r=p(p為最后結點賦給r),p->=NULL
3.11 單鏈表結構優點:插入刪除時間O(1),不需要預分配;
確定:查找O(n)
3.12 靜態鏈表:用數組描述的鏈表;
優點:插入刪除只需修改游標;
缺點:表長依然難以確定,失去順序存儲結構的隨機性;
3.13 循環鏈表:將單鏈表中終端結點的指針端由空指針改為頭指針;
3.14 雙向鏈表:在單鏈表的每個節點中,再設置一個指向其前驅結點的指針域;(空間換時間)
插入時需要保證p->next的賦值在四個操作中最后進行
4 棧
限定僅在表尾進行插入和刪除操作的線性表;
后進先出,操作在棧頂進行,后進先出(LIFO結構);
進棧,壓棧:插入操作
出棧:刪除操作
4.6.1 棧的鏈式存儲結構,鏈棧;
鏈棧:空間大小可不確定 ; 順序棧:空間大小確定
棧的作用:有效解決遞歸問題
遞歸:直接調用自己或通過一系列的語句間接調用自己的函數;
迭代:循環結構; 遞歸:選擇結構;
后綴表達式:逆波蘭;
中綴表達式:標准四則運算表達式;
4.9.3 中綴轉后綴:從左到右遍歷中綴表達式每個數字和符號,若是數字就輸出,即成為后綴表達式的一部分;若是符號,則判斷其與棧頂符號的優先級,是右括號或優先級低於棧頂符號則棧頂元素依次出棧並輸出,並將當前符號進棧,一直到最終輸出后綴表達式為止;
4.10 隊列:允許在一段進行插入操作,在另一端進行刪除操作的線性表;
first in first out(FIFO)
隊尾:允許插入; 隊頭:允許刪除;
隊列順序存儲不足,刪除隊頭,需要移動這個數組O(n);
front指向隊頭元素,rear指向隊尾元素;
front = rear 空隊列
循環隊列:頭尾相接;設置flag,以區別front = rear時為空還是滿;
4.13 隊列等鏈式存儲結構
就是線性表的單鏈表,但只能尾進頭出,鏈隊列;
空隊列:front和rear指向頭結點;
5 串
是由零個或多個組成的有限序列,字符串;
空格串:只包含空格的串; 空串:零個字符串;
模式匹配算法,克努特-莫里斯-普拉斯算法(KMP模式)(沒看懂)
http://blog.csdn.net/joylnwang/article/details/6778316
6 樹
n(n≥0)個結點的有限集。n=0時稱為空樹。在任意一顆非空樹中:有且僅有一個特定的稱為根(Root)的結點;當n>1時,其余結點可分為m(m>0)個互不相交的有限集T1,T2...Tn,其中每一個集合本身又是一顆樹,並且稱為根的子樹(SubTree)。
結點擁有的子樹的數稱為結點的度(Degree)。度為0度結點稱為葉結點(Leaf)或終端結點;度不為0的結點稱為非終端結點或分支結點,也稱為內部結點。樹的度是樹內各結點的度的最大值。
結點子樹的根稱為該結點的孩子(Child),該結點稱為孩子的雙親(Parent)。同一個雙親的孩子之間互稱兄弟(Sibling)。結點的祖先是從根到該結點所經分支上的所有結點。
結點的層次從根開始定義,根為第一層,根的孩子為第二層。樹中結點的最大層次稱為樹的深度(Deoth)或高度。
如果將樹中結點的各子樹看成從左至右是有次序的,不能互換的,則稱該樹為有序樹,否則稱為無序樹。森林是棵互不相交的樹的集合。
6.5 二叉樹(Binary Tree):n(n≥0)個結點的有限集合,該集合或者為空集,或者由一個根結點和兩棵互不相交的,分別為根結點的左子樹和右子樹的二叉樹組成。
特點:每個節結點最多兩棵子樹,即度不大於2,左右子樹次序一定;
五種基本形態:空二叉樹,只有一個根結點,根結點只有左子樹,根結點只有右子樹,根結點既有左子樹又有右子樹;
6.5.2 斜樹:所有結點都只有左子樹為左斜樹,只有右子樹為右斜樹,這兩種統稱斜樹;
滿二叉樹:所有分支結點都存在左子樹和右子樹,並且所有葉子都在同一層上;
完全二叉樹:一個有n個結點的二叉樹按層序編號,如果編號為i的結點與同樣深度的滿二叉樹中編號為i的結點在二叉樹中位置完全相同,則這棵二叉樹稱為完全二叉樹;
滿二叉樹一定是完全二叉樹,但完全二叉樹不一定是滿二叉樹;
完全二叉樹特點:葉子結點只能出現在最下兩層;最下層的葉子一定集中在左部連續;倒數二層若有葉子結點,一定都在右部連續位置;當結點度為1,則該結點只有左孩子;同樣結點樹的二叉樹,完全二叉樹的深度最小;
二叉樹性質
1:在二叉樹的第i層上至多有2^(i-1)個結點(i≧1);
2:深度為k的二叉樹至多有(2^k)-1個結點(k≧1);
3:任意一棵二叉樹T,如果終端結點數為n0,度為2的結點數為n2,則n0=n2+1;
4:具有n個結點的完全二叉樹深度為「㏒2(n) 」+1(「x」表示不大於x的最大整數)
5:如果對一棵有n個結點的完全二叉樹的結點按層序編號(從第1層到第「㏒2(n) 」+1層),對任意一結點有:
如果i=1,則結點i是二叉樹的根,無雙親;i≧1,則其雙親是結點「i/2」;
如果2*>n,則結點i無左孩子(結點i為葉子結點);否則其左孩子是結點2*i;
如果2*i>n,則結點i無右孩子;否則其右孩子是結點2*i+1;
6.7 二叉樹的存儲結構
二叉鏈表:鏈表中結點設計一個數據域和兩個指針域(表示兩個孩子)
6.8 二叉樹都遍歷:
從根結點出發,按照某種次序依次訪問二叉樹中所有結點,使得每個節點被訪問一次且僅被訪問一次;
前序遍歷:若二叉樹為空,則空操作返回,否則先訪問根結點,然后前序遍歷左子樹,再前序遍歷右子樹;
中序遍歷:若樹為空,則空操作返回,否則從根結點開始(並不是先訪問根結點),中序遍歷根結點左子樹,然后訪問根結點,最后中序遍歷右子樹;
后序遍歷:若樹為空,則空操作返回,否則從左到右先葉子后結點到方式遍歷訪問左右子樹,最后訪問根結點;
層序遍歷:若樹為空,則空操作返回,否則從樹第一層,也就是根結點開始訪問,從上而下逐層遍歷,同一層從左到右順序訪問;
6.8.6 二叉樹遍歷性質
已知前序遍歷序列和中序遍歷序列可以唯一確定一棵二叉樹;
已知后序遍歷序列和中序遍歷序列可以唯一確定一棵二叉樹;
6.9 二叉樹的建立
擴展二叉樹:將二叉樹的每個結點的空指針引出一個虛結點,其值為一特定值;
6.10 線索二叉樹
指向前驅和后繼的指針稱為線索,加上線索的二叉鏈表稱為線索鏈表,相應的二叉樹稱為線索二叉樹;
線索化:對二叉樹以某種次序遍歷使其變為線索二叉樹的過程;
6.12 赫夫曼編碼
帶權路徑長度WPL最小的二叉樹稱作赫夫曼樹;
7 圖
由頂點的有窮非空集合和頂點之間邊的集合組成,通常表示為:G(V,E),其中,G表示一個圖,V是圖G中頂點的集合,E是圖G中邊的集合;
圖中數據元素稱為頂點;
圖結構中不允許沒有頂點;
任意兩點之間都可能有關系,頂點之間的邏輯關系用邊來表示,邊集可以為空;
7.2.1 各種圖定義
無向邊:頂點V1和Vi之間的邊沒有方向,則稱這條邊為無向邊(Edge),用無序偶對(Vi Vj)來表示;
如果圖中任意兩個頂點之間的邊都是無向邊,則稱該圖為無向圖;
有向邊:若頂點從V1到Vi的邊有方向,則稱這條邊有方向,也稱為弧(Arc),用有序偶
<Vi Vj>表示,Vi稱為弧尾(Tail),Vj為弧頭(Head);
若圖中任意兩個頂點之間的邊都是有向邊,則稱該圖為有向圖;如:頂點A到D的有向邊,A是弧尾,D是弧頭,<A,D>表示弧;
簡單圖:若不存在頂點到其自身的邊且同一條邊不重復出現;
無向完全圖:在無向圖中任意兩個頂點都存在邊;含有n個頂點的完全圖有n*(n-1)/2條邊;
有向完全圖:有向圖中任意兩個頂點之間都存在方向互為相反的兩天弧,有n*(n-1)條邊;
有很少條邊或弧度圖稱為稀疏圖,反之稱為稠密圖;
圖的邊或弧相關的樹叫做權(Weight),帶權的圖稱為網(Network);
假設圖G=(V,{E}),圖G'=(V',{E'}),如果V'⊆V且E'⊆E,則稱G'為G的子圖(Subgraph);
對於無向圖G=(V,{E}),如果邊(v,v')∈E,則稱頂點v和v'互為鄰接點,即v和v'相領接邊(v,v')依附於頂點v和v',頂點v的度是和v相關聯的邊的數目,記為TD(v);
邊數就是各頂點度數和道一半:e= 0.5* ∑TD(vi) (i=1,2,3...n)
對於有向圖G=(V,{E}),以頂點v為頭的弧度數目稱為v的入度,記為ID(v),以v為尾的弧的數目稱為v的出度,記為OD(v);頂點v的度為TD(v)=ID(v)+OD(v);
無向圖中從頂點v到頂點v'的路徑是一個頂點序列;有向圖的路徑也是有向的;
路徑的長度是路徑上的邊或弧度數目;
第一個頂點到最后一個頂點相同的路徑稱為換或回路,序列中不重復出現的路徑稱為簡單路徑;
7.2.3 連通圖
無向圖中,從頂點v到v‘有路徑則稱為v和v’是連通的;如果對於圖中任意兩點都是連通的,則稱圖是連通圖;
無向圖中的極大連通子圖稱為連通分量;
連通分量條件:子圖/子圖連通/連通子圖含有極大頂點樹/具有極大頂點數的連通子圖包含依附於這些頂點的所有邊;
在有向圖G中,如果每一對v,v‘∈V,v≠v’,從v到v‘和從v’到v都存在路徑,則稱G是強連通圖;有向圖中的極大強連通子圖稱作有向圖的強連通分量;
一個連通圖的生成樹是一個極小的連通子圖,它含有圖中全部的n個頂點,但只有足以構成一棵樹的n-1條邊;
如果一個有向圖恰有一個頂點的入度為0,其余頂點的入度均為1,則是一棵有向樹;
一個有向圖的生成森林由若干棵有向樹組成,含有圖中全部頂點,但只有足以構成若干棵不相交的有向樹的弧;
7.4 圖的存儲結構
7.4.1 鄰接矩陣:一個一維數組存儲圖中頂點信息,一個二維數組存儲圖中的邊或弧度信息;
二維數組就是矩陣形式存儲,v[i][j]表示頂點i到j的邊或弧;
n個頂點和e條邊的無向網圖創建時間復雜度O(n*n+n+e);
7.4.2 鄰接表:數組與鏈表相結合的存儲方式
頂點右一位數組存儲,每個數據元素存儲指向第一個領接點的指針,每個頂點的所有領接點構成一個線性表;
有向圖的逆鄰接表:對每個頂點vi建立一個鏈接為vi為弧頭的表;
7.4.3 十字鏈表
將鄰接表和你鄰接表結合起來;
結點存儲數據/入邊表頭指針/出邊表頭指針;
7.4.4 鄰接多重表
7.4.5 邊集數組
由兩個一維數組構成,一個是存儲頂點的信息;另一個存儲邊的信息,這個邊數組每個數據元素由一條邊的起點下表,終點下表和權組成;
7.5 圖的遍歷
從圖中某一頂點出發遍歷圖中其余頂點,且每個頂點僅被訪問一次,稱為圖的遍歷;
深度優先遍歷:從某頂點v出發,訪問該頂點,然后從v的未被訪問鄰接點出發深度優先遍歷圖,直到圖中所有和v有路徑相同的頂點都被訪問;
7.5.2 廣度優先遍歷
與深度優先遍歷時間復雜度相同;(類似樹的層序遍歷)
7.6 最小生成樹
構造連通網的最小代價生成樹稱為最小生成樹;
7.6.1 普里姆(Prim)算法
時間復雜度:O(n*n);
7.6.2 克魯斯卡爾(Kruskal)算法
時間復雜度O(e*log e)
7.7 最短路徑
迪傑斯特拉算法:時間復雜度O(n*n);
弗洛伊德算法:時間復雜度O(n*n*n);
7.8 拓撲排序
AOV網:在一個表示工程的有向圖中,用頂點表示活動,用弧表示活動間的優先關系;
拓撲序列:有向圖G,滿足從頂點vi到vj有一條路徑,則在頂點序列中頂點vi必在vj之前;
拓撲排序:對一個有向圖構造拓撲序列對過程;
時間復雜度:O(n+e)
AOE網:在一個表示工程的帶權有向圖中,用頂點表示事件,用有向邊表示活動,用邊上的權值表示活動的持續時間,
7.9 關鍵路徑:
從源點到匯點具有最大路徑;
8 查找
根據給定某個值,在查找表中確定一個其關鍵字等於給定值的數據元素(或記錄);
查找表:由同一類型的數據元素構成的集合;
關鍵字:數據元素中某個數據項的值,又稱鍵值;
主關鍵字:此關鍵字可以唯一表示一條記錄;
數據項對應數據碼;
查找:根據給定的某個值,在查找表中確定一個其關鍵字等於給定值的數據元素(或記錄);
靜態查找表:只做查找操作的查找表;
動態查找表:在查找過程中同時插入不存在的數據元素,或者從查找表中刪除已經存在的某個數據元素
8.3 順序表查找
順序查找/線性查找:從表中第一個(或最后一個)記錄開始,逐個進行記錄的關鍵字和給定值比較,若相等則查找成功,直到最后一個(或第一個)記錄,不等則查找不成功;
順序查找優化:將給定值賦予a[0],從尾部遍歷,循環條件為是否等於關鍵字,省去判斷越界環節;
8.4 有序表查找
二分查找/折半查找:在有序表中,取中間記錄作為比較對象,若給定值與關鍵字相等則成功,小於則在左半區查找,大於在右半區查找,直到成功或查找所有區域無記錄而查找失敗(前提為線性表中記錄必須是關鍵碼有序,通常從小到大,且為順序結構);
時間復雜度O(log n);
插值查找:根據要查找的關鍵字key與查找表中最大最小記錄的關鍵字比較后查找,將二分查找的mid設為mid = low + (key - a[low])/(a[high] - a[low]) * (high - low)
斐波那契查找:利用斐波那契函數給mid賦值,mid=low+F[k-1]-1;
時間復雜度O(log n);
8.5 線性索引查找
索引就是把一個關鍵字與它對應的記錄相關聯的過程;
線性索引:將索引項集合組織為線性結構,也稱索引表;
8.5.1稠密索引
在線性索引中,將數據集中的每個記錄對應一個索引項;
索引項一定是按照關鍵碼有序排列;
8.5.2分塊索引
分塊有序,是把數據集的記錄分成若干塊,並且這些快需要滿足,塊內無序,塊間有序;
塊間有序:要求第二塊所有記錄關鍵字均大於第一塊中所有記錄的關鍵字;
最佳分塊索引情況為塊m=√ ̄n(n為記錄數),此時平均查找長度L=(√ ̄n)+1;
8.5.3倒敘索引
記錄號表存儲具有相同次關鍵字的所有記錄的記錄號(可以是指向記錄的指針或者是該記錄的主關鍵字),由屬性值來確定記錄的位置;
8.6 二叉排序樹
二叉查找樹/二叉排序樹:
若它的左子樹不空,則左子樹上所有結點的值均小於它的根結構的值,
若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值,
它的左右子樹也分別為二叉排序樹;
二叉排序樹查找:利用遞歸在二叉鏈表中遞歸查找;
二叉排序樹插入操作:利用查找函數將key插入到最終查找到合適結點到子樹上;
二叉排序樹構建:利用插入函數構建(根結點,將之后元素與結點對比,小的在左樹中去對比,大的在右樹中去對比,直到結點沒有孩子,則插入);
二叉排序樹刪除:找到刪除的結點的直接前驅,用該前驅替換刪除的結點;
二叉排序樹以鏈接的方式存儲
8.7 平衡二叉樹
--是一種二插排序樹,其中每一個節點的左子樹和右子樹高度差至多等於1;
平衡因子:左子樹與右子樹深度差值;
最小不平衡子樹:距離插入節點最近的,且平衡因子的絕對值大於1的結點為根的子樹;
8.8 多路查找樹(B樹)
每一個結點孩子樹可以多於兩個,且每一個結點處可以存儲多個元素;
2-3樹:
每個結點有兩個2個孩子(2結點)或3個孩子(3結點);
一個2結點包含一個元素和兩個孩子(或沒有孩子);
一個3結點包含一小一大兩個元素和3個孩子(或沒有孩子);
所有葉子在同一層次上;
2-3-4樹:
2-3樹的擴展,包括4結點;
一個4結點包括小中大3個元素和4個孩子(或沒有孩子);
B樹(B-tree):一種平衡的多路查找樹,結點最大的孩子數目稱為B樹的結;(2-3樹是3階B樹)
如果根結點不是葉結點,則至少有兩棵子樹;
8.9 散列查找
散列技術:在記錄的存儲位置和它的關鍵字之間建立一個確定的對應關系f,使得每個關鍵字k對應一個存儲位置;散列函數(哈西函數)
K1≠K2,但f(K1)=f(K2),此時稱為沖突,K1和K2稱為這個散列函數的同義詞;
8.10 散列函數的構造方法
直接定值;數字分析法;平方取中;折疊法;除留余數法;
8.11 處理散列沖突
開放定值法:一旦發生沖突,就去尋找下一個空的散列地址;
再散列函數法:發生沖突,更換散列函數進行計算;
鏈地址法:發生沖突,在當前位置給單鏈表增加結點;
公共溢出法:給發生沖突的關鍵字重新建立一個溢出表;
8.12 散列表查找
9 排序
似的序列成為一個按關鍵字有序的序列;
排序穩定:Ki=Kj,且排序前Ri領先於Rj,排序后任然領先;
排序不穩定:Ki=Kj,且排序前Ri領先於Rj,排序后Rj領先Ri;
內排序:排序過程待排序所有記錄放置在內存中;
外排序:整個排序過程需要在內外存之間切換;
性能影響:
1 時間性能:盡可能少的關鍵字比較次數和盡可能少的紀錄移動次數;
2 輔助空間:存放待排序占用空間加上執行算法所需要其他存儲空間;
3 復雜性: 算法本身復雜度,不止時間;
9.3 冒泡:
時間:O(nˇ2);
9.4 簡單排序:
通過n-i次關鍵字比較,從n-i+1個記錄中選出關鍵字最小的值,並和第i個交換;
時間:O(nˇ2);
略優於冒泡(每次只交換一個值);
9.5 直接插入:
將一個記錄插入到已排序的序表中;
時間:O(nˇ2);
略優於冒泡(比較次數少);
9.6 希爾排序:
基本有序:小的關鍵字基本在前面,大的基本在后面,不大不小的基本在中間;
時間:O(nˇ(2/3));
9.7 堆排序:
堆:完全二叉樹;
大頂堆:每個結點堆值都大於或等於其左右孩子結點的值;
小頂堆:每個結點堆值都小於或等於其左右孩子結點的值;
堆排序(大頂堆):將待排序序列構造一個大頂堆;最大值此時在根結點,移走根結點,剩余n-1個結點從新構造一個堆,得到次小值,如此反復得到一個有序序 列;
let maxsize = 10
struct Sqlist {
var arr: [Int] = [maxsize + 1]
var length: Int?
}
//堆排序
func heapSort(L: Sqlist) {
for i in L.arr.count...0 {
heapAdjust(L, s: i, m: L.arr.count)
}
for i in L.arr.count...1 {
swap(L.arr, i: 1, j: i)
heapAdjust(L, s: 1, m: i-1)
}
}
func heapAdjust(var L: Sqlist,var s: Int, m: Int) {
let temp = L.arr[s]
for (var j = 2*s; j<=m; j=j*2) {
if (j<m && L.arr[j] < L.arr[j+1]) {
j += 1
}
if temp >= L.arr[j] {
break
}
L.arr[s] = L.arr[j]
s = j
}
L.arr[s] = temp
}
//直接插入排序
func insertSort(var L: Sqlist) {
for i in 1...(L.arr.count - 1) {
if L.arr[i] < L.arr[i-1] {
let temp = L.arr[i]
for j in i...0 {
if L.arr[j] < temp {
L.arr[j] = L.arr[j-1]
L.arr[j-1] = temp
}
}
}
}
}
//選擇排序
func selectSort(L: Sqlist) {
for i in 0...(L.arr.count - 1) {
var min = i
for j in 1...(L.arr.count - i) {
if L.arr[min] > L.arr[j] {
min = j
}
}
if i != min {
swap(L.arr, i: i, j: min)
}
}
}
//冒泡優化---可以避免再有序化后再進行判斷的多余操作;
func optimizeBubbkeSort(L: Sqlist) {
var flag = true
for i in 0...(L.arr.count - 1) {
if flag {
flag = false
}else {
return
}
for j in 1...(L.arr.count - i) {
if L.arr[j-1] > L.arr[j] {
swap(L.arr, i: j-1, j: j)
flag = true
}
}
}
}
//冒泡
func bubbleSort(L: Sqlist) {
for i in 0...(L.arr.count-1){
for j in (L.arr.count-1)...i {
if L.arr[j-1] > L.arr[j] {
swap(L.arr, i: j-1, j: j)
}
}
}
}
//交換位置
func swap(var L: [Int], i: Int, j: Int) {
let temp = L[i]
L[i] = L[j]
L[j] = temp
}
You got a dream, you gotton protect it. People can not do something themselves, they wanna tell you you can not do it. If you wanna something, go get it. Period.
