大話數據結構個人筆記


作為一個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.

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM