1. 程式人生 > >數據結構基本知識點總結

數據結構基本知識點總結

ttr 連通 稀疏圖 邏輯結構 時也 實現 alt 相關 散列

1,

數據結構三要素:
  1,邏輯結構:線性和非線性
  2,存儲結構:順序,鏈式,索引,散列
  3,數據運算:算法

  具體時間復雜度與問題的規模和初始條件相關,分最佳和最大

2,

線性表:

無頭結點:
  頭插法:s->data=ch;s->next=head;head=s;
  尾插法:rear->next=s;rear=s; (兩個指針頭尾指針)
  刪除:q=p->next;p->next=q->next;free(q);
有頭結點:有了頭結點後,對在第一個元素結點前插入結點和刪除第一個結點,其操作與對其它結點的操作統一了。

  頭插法:s->data=ch;s->next=head->next;head->next=s;
  尾插法:rear->next=s;rear=s; (兩個指針頭尾指針)
  刪除:q=p->next;p->next=q->next;free(q);
循環鏈表:


單循環鏈表中設置尾指針比設置頭指針更好
雙循環鏈表:
  前插:s->data=ch;s->prior=p->prior;s->next=p;p->prior->next=s;p->prior=s;
  刪除:p->prior->next=p->next;p->next->prior=p->prior;free(p);

鏈表逆序:

 public static Node reversed_linkedlist() {
        MyLinkedList list = new MyLinkedList();
        Node head 
= list.init(); if(head == null || head.next == null) { return head; } //使用三個節指針 Node current = head; Node newHead = null; Node next = null; while(current != null) { //先將當前節點的下個節點保存 next = current.next; current.next
= newHead; //將原來的鏈表斷鏈,將current的下一個結點指向新鏈表的頭結點 newHead = current; //將current設為新表頭 current = next; //將之前保存的next設為下一個節點 } return newHead; }

3,

棧:
順序棧:(棧頂插入和刪除,棧底為0)

  •   初始棧:s->top=-1;
  •   進棧:s->top++;S->data[s->top]=x;
  •   出棧:x=S[s->top];s->top--;

鏈棧:鏈棧是沒有附加頭結點的運算受限的單鏈表。棧頂指針就是鏈表的頭指針

  •   進棧:p->data=x;p->next=S->top;S->top=p;(先進後出)S的next指向前面
  •   出棧:S->top=p->next;free(p);

隊列:

隊頭刪除,隊尾插入(銀行排隊)
順序隊列:
front和rear分別隊頭指針始終指向隊頭元素,尾指針始終指向隊尾元素的下一位置
循環隊列:為區分隊列空和滿:1,添加一個空;2,添加計數項

  •   入隊:Q->count++;Q->data[Q->rear]=x;Q->rear=(Q->rear+1)%QueueSize;
  •   出隊:Q->count--;Q->front=(Q->front+1)%QueueSize;

鏈式隊列:

  • 入隊:p->data=x;Q->rear->next=p;Q->rear=p;
  • 出隊:p=Q->front;Q->front=p->next;free(p);

4,

樹:
層次:根為第一層,最大層為樹的高度,深度為根到該節點的路徑長度;高度為葉節點到該節點最大路徑
二叉樹性質
  1,二叉樹第i層上的結點數目最多為2i-1(i≥1)。
  2,深度為k的二叉樹至多有2^k-1個結點(k≥1)
  3,在任意-棵二叉樹中,若終端結點的個數為n0,度為2的結點數為n2,則no=n2+1
  4,具有n個結點的完全二叉樹的深度為:log2[n](向下)+1或log2[n+1](向上)

二叉樹存儲形式:
  1,順序存儲:第i個結點的孩子是2i,2i+1 (完全二叉樹適用,如果該樹不是完全二叉樹,需要添加空節點構成完全二叉樹)
  2,二叉鏈表結構:左右指針,中間數據 |left|data|right|
二叉樹遍歷:

遍歷是樹進行其他運算的基礎,前+中,中+後,層次+中(因為前後可以推出根結點,而中可以推左右) 使用遞歸思想來推樹的結構能夠快些
如:前+中
前:GDAFEMHZ 中:ADEFGHMZ
步驟:根據前知道root是G,根據中知道左子樹是ADEF,右子樹是HMZ
  分析leftTree,由前知道root是D,so leftTree is:A,and rightTree is :EF
  分析leftTree A ,結束,分析rightTree,From 前知道root 是F,From 中知leftTree is E
  分析rigthTree HMZ,From 前知root is M,From 中知 leftTree is H,and rightTree is Z
  遍歷結束,樹的層次遍歷為 GDMAFHZE
如:中+後
中:ADEFGHMZ 後:AEFDHZMG
步驟:From 後,知道root 是G,From中知leftTree is ADEF,rightTree is HMZ;
   分析leftTree:From 後知root is D,From 中leftTree is A ,rightTree is EF;
  分析rightTree EF;From 後知:root is F,From 中leftTree is E;
  分析rightTree HMZ;From 後知root is M ,From 中leftTree is H,rightTree is Z;
  遍歷結束,層次遍歷為:GDMAFHZE

線索二叉樹:左右標簽為0,表示左右指針指向左右孩子節點,若為1,指向其左指向前驅,右指向後繼(方便前,中,後遍歷)
樹轉二叉樹:二叉樹左子樹為樹的子節點,右子樹為兄弟,單個樹即只有左側,同樣森林可以是左右子樹的二叉樹
同理二叉樹轉回森林和樹:類似
樹存儲結構:
  1,雙親鏈表表示法利用樹中每個結點的雙親唯一性,在存儲結點信息的同時,為每個結點附設一個指向其雙親的指針parent,惟一地表示任何-棵樹。
  2,孩子鏈表表示法是為樹中每個結點設置一個孩子鏈表,並將這些結點及相應的孩子鏈表的頭指針存放在一個向量中。類似hash
  3,在存儲結點信息的同時,附加兩個分別指向該結點最左孩子和右鄰兄弟的指針域leftmostchild和rightsibling,即可得樹的孩子兄弟鏈表表示。
這種存儲結構的最大優點是:它和二叉樹的二叉鏈表表示完全一樣
樹(森林)的前序遍歷:前序遍歷一棵樹(森林)恰好等價於前序遍歷該樹(森林)對應的二叉樹
後序遍歷樹(森林)恰好等價於中序遍歷該樹(森林)對應的二叉樹

樹的路徑:樹的路徑長度是從樹根到樹中每一結點的路徑長度之和。在結點數目相同的二叉樹中,完全二叉樹的路徑長度最短。
樹的代價結點的帶權路徑長度:結點到樹根之間的路徑長度與該結點上權的乘積
帶權路徑長度最小(即代價最小)的二叉樹稱為最優二叉樹或哈夫曼樹。
哈夫曼樹:
1,n個葉子的哈夫曼樹要經過n-1次合並,產生n-1個新結點。最終求得的哈夫曼樹中共有2n-1個結點。
2,哈夫曼樹是嚴格的二叉樹,沒有度數為1的分支結點。

哈夫曼編碼方式:

定長編碼:如有6個字符,則n的位數定義為log26的上限為3位,定長為3位:000,001,010,011,100,101

變長編碼:哈夫曼編碼,根據樹的深度,左子樹為0,右子樹為1:根:0,00,010等

技術分享

用途:
編碼:將每個字符編碼成二進制位串
解碼:將二進制位串轉為字符
變長編碼方案:變長編碼方案將頻度高的字符編碼設置短,將頻度低的字符編碼設置較長
哈夫曼編碼:壓縮文件
1,構造哈夫曼樹,確定每個單詞所在的層次(n n=1,..),即哈夫曼二進制
2,計算代價:每個單詞(葉節點)的層次(n-1)*單詞出現的次數(權重值)之和為哈夫曼代價,實現壓縮。

                技術分享

5,

圖G的頂點數n和邊數e的關系

  若G是無向圖,則0≤e≤n(n-1)/2
  若G是有向圖,則0≤e≤n(n-1)
無向圖的度:無向圖中頂點v的度(Degree)是關聯於該頂點的邊的數目,記為D(v),不分出度和入度
有向圖的度:入度:以頂點v為終點的邊的數目稱為v的入度(Indegree);出度:以頂點v為始點的邊的數目
      圖的邊數等於度之和除以2
連通圖:若V(G)中任意兩個不同的頂點vi和vj都連通

有向邊也稱為弧(Arc),邊的始點稱為弧尾(Tail),終點稱為弧頭(Head)。
強連通圖:有向圖G中,若對於V(G)中任意兩個不同的頂點vi和vj,都存在從vi到vj以及從vj到vi的路徑,則稱G是強連通圖。
若將圖的每條邊都賦上一個權,則稱這種帶權圖為網絡
圖鄰接矩陣:時間復雜度O(n^2)

技術分享

技術分享

圖鄰接表:時間復雜度O(n+e)

表結點結構:鄰接點域adjvex:存放與vi相鄰接的頂點vj的序號j。鏈域next:將鄰接表的所有表結點鏈在一起
頭結點結構:頂點域vertex:存放頂點vi的信息;指針域firstedge:vi的鄰接表的頭指針
有向圖分為:出邊表和入邊表

        技術分享

圖遍歷:

              技術分享

深度遍歷:

使用棧,時間復雜度為O(n^2)(鄰接矩陣)O(n+e)(鄰接表)

上圖的深度遍歷: v0,v1,v2,v5,v4,v6,v3,v7

廣度遍歷:
使用隊列:先進先出 時間復雜度為O(n^2)(鄰接矩陣)O(n+e)(鄰接表)

上圖廣度遍歷是:V0,V1,V3,V4,V2,V6,V5,V7

生成樹:
連通圖G的一個子圖是一棵包含G的所有頂點的樹,則該子圖稱為G的生成樹 (最小連通子圖)
最小生成樹:針對帶權的網絡,計算出整個網絡通信所需要的最小成本
普利姆算法(prim):時間復雜度O(n^2),與圖的邊數無關,適合稠密圖
流程初始頂點,選擇其鄰居中最小的邊,更新鄰居的邊集,依次進行,直到所有頂點加入到生成樹中

技術分享

克魯斯卡爾(Kruskal)算法:時間復雜度O(elge),適合稀疏圖
流程:提取邊的集合;找權值最小的邊,尋找下一條邊(如果該邊使圖變為環,舍去),直到全部頂點變為生成樹時,結束

技術分享

最短路徑:

Dijkstra(迪傑斯特拉)算法是典型的單源最短路徑算法,用於計算一個節點到其他所有節點的最短路徑。O(N^2) 不能計算權重為負,適合有向圖計算如:

技術分享

技術分享

Floyd算法:是解決任意兩點間的最短路徑的一種算法,可以正確處理有向圖或負權的最短路徑問題,同時也被用於計算有向圖的傳遞閉包。Floyd-Warshall算法的時間復雜度為O(N3),空間復雜度為O(N2)。核心檢查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,流程具體如下:

技術分享

2階矩陣求法:從橫豎交處為起始點a[0][0],選橫線某點i為a[0][1]點,a[1][1]選i列不在斜線上的第j行的點, a[1][0]選取豎線上的第j行的點。判斷方法:如果a[0][0]+a[0][1]+a[1][0]<a[1][1],則用相加值替代原先A[i][j]上的值。n行n列一次可以得到(n-1)*(n-2)各小矩陣,總共更新n次,獲取到每個點之間的最短路徑。

技術分享

技術分享

矩陣A3為最後結果每個點到其它點的最短路徑,矩陣Path記錄u,v兩點之間最短路徑所必須經過的點-------------------》參考博客和網站

最小生成樹能夠保證整個拓撲圖的所有路徑之和最小,但不能保證任意兩點之間是最短路徑。
最短路徑是從一點出發,到達目的地的路徑最小。(註意最小生成樹prim和dijiksd算法不同)

拓撲排序:針對有向無環圖,表示事件發生的先後順序

參考網址和練習題:http://xu-laoshi.cn/shujujiegou/xiti_07_1.html

數據結構基本知識點總結