樹與樹的表示

1、什麼是樹

客觀世界中許多事物存在層次關係算法

  • 人類社會家譜
  • 社會組織結構
  • 圖書信息管理

其中,人類社會家譜以下圖所示:數組

經過上述所說的分層次組織,可以使咱們在數據的管理上有更高的效率!那麼,對於數據管理的基本操做——查找,咱們如何實現有效率的查找呢?數據結構

2、查找

查找:根據某個給定關鍵字K,從集合R中找出關鍵字與K相同的記錄spa

靜態查找:集合中記錄是固定的,即對集合的操做沒有插入和刪除,只有查找3d

動態查找:集合中記錄是動態變化的,即對集合的操做既有查找,還可能發生插入和刪除(動態查找不在咱們考慮範圍內指針

2.1 靜態查找

2.1.1 方法1:順序查找

/* c語言實現 */

int SequentialSearch (StaticTable *Tbl, ElementType K)
{
// 在表Tbl[1]~Tb1[n]中查找關鍵字爲K的數據元素
  int i;
  Tbl->Element[0] = K; // 創建哨兵,即沒找到能夠返回哨兵的索引0表示未找到
  for (i = Tbl->Length; Tbl->Element[i] != K; i--); // 查找成功返回所在單元下標;不成功放回0
  return i;
}

順序查找算法的時間複雜度爲O(n)code

假設n個數據元素的關鍵字知足有序(好比:小到大),即\(k_1<k_2<\cdots<k_n\),而且是連續存放(數組),那麼能夠進行二分查找。blog

例:假設有13個數據元素,按關鍵字由小到大順序存放。二分查找關鍵字爲444的數據元素過程以下圖:索引

仍然以上面13個數據元素構成的有序線性表爲例,二分查找關鍵字爲43的數據元素以下圖:

/* c語言實現 */

int BinarySearch (StaticTable *Tbl, ElementType K)
{
  // 在表中Tbl中查找關鍵字爲K的數據元素
  int left, right, mid, NoFound = -1;
  
  left = 1; // 初始左邊界
  right = Tbl->Length; // 初始右邊界
  while (left <= right)
  {
    mid = (left + right) / 2; // 計算中間元素座標
    if (K < Tbl->Element[mid]) right = mid - 1; // 調整右邊界
    else if (K > Tbl->Element[mid]) left = mid + 1; // 調整左邊界
    else return mid; // 查找成功,返回數據元素的下標
  }
  return NotFound; // 查找不成功,返回-1
}
# python語言實現

def binary_chop(alist, data):
    n = len(alist)
    first = 0
    last = n - 1
    while first <= last:
        mid = (last + first) // 2
        if alist[mid] > data:
            last = mid - 1
        elif alist[mid] < data:
            first = mid + 1
        else:
            return True
    return False

二分查找算法具備對數的時間複雜度O(logN)

二分查找算法雖然解決了查找的時間複雜度問題,可是對於數據的插入和刪除確是O(n)的,所以有沒有一種數據結構,既能夠減小數據查找的時間複雜度,又能夠減小數據的插入和刪除的複雜度呢?

3、二分查找斷定樹

除了使用上述兩個方法進行關鍵字的查找,咱們還能夠經過二叉樹這種數據結構完成關鍵字的查找。

從上圖能夠看出,若是咱們須要尋找數字8,能夠經過如下4步實現(可能看不懂,將來會看得懂):

  1. 根節點6小於8,往6的右子節點9找
  2. 結點9大於8,往9的左子結點7找
  3. 結點7小於8,往7的左子結點找
  4. 找到8
  • 斷定樹上每一個結點須要的查找次數恰好爲該結點所在的層數;
  • 查找成功時查找次數不會超過斷定樹的深度
  • N個結點的斷定樹的深度爲\([log_2{n}]+1\)
  • \(ASL = (4*4+4*3+2*2+1)/11 = 3\)

4、樹的定義

樹(Tree):\(n(n\geq{0})\)個結點構成的有限集合。

  • 當n=0時,稱爲空樹
  • 對於任一顆非空樹(n>0),它具有如下性質:
    • 樹中有一個稱爲根(Root)的特殊結點,用r表示
    • 其他結點可分爲m(m>0)互不相交的有限集\(T_1,T_2,\cdots,T_m\),其中每一個集合自己又是一棵樹,稱爲原來樹的子樹(SubTree)

5、樹與非樹

牢記樹有如下3個特性:

  1. 子樹是不相交的;
  2. 除了根結點外,每一個結點有且僅有一個父結點
  3. 一顆N個結點的樹有N-1條邊

5.1 非樹

5.2 樹

6、樹的一些基本術語

  1. 結點的度(Degree):結點的子樹個數
  2. 樹的度:樹的全部結點中最大的度數
  3. 葉結點(Leaf): 度爲0的結點
  4. 父結點(Parent):有子樹的結點是其子樹的根結點的父結點
  5. 子結點(Child):若A結點是B結點的父結點,則稱B結點是A結點的子結點;子結點也稱孩子結點
  6. 兄弟結點(Sibling):具備同一父結點的各結點彼此是兄弟結點

  7. 路徑和路徑長度:從結點\(n_1\)\(n_k\)路徑爲一個結點序列\(n_1 , n_2 ,\cdots, n_k\) , \(n_i\)\(n_{i+1}\)的父結點。路徑所包含邊的個數爲路徑的長度

  8. 祖先結點(Ancestor):沿樹根到某一結點路徑上的全部結點都是這個結點的祖先結點
  9. 子孫結點(Descendant):某一結點的子樹中的全部結點是這個結點的子孫

  10. 結點的層次(Level):規定根結點在1層,其它任一結點的層數是其父結點的層數加1

  11. 樹的深度(Depth):樹中全部結點中的最大層次是這棵樹的深度

7、樹的表示

7.1 樹的鏈表表示

上圖所示樹的鏈表表示法有很大的缺陷,假設樹的深度很是大,而且不能保證全部樹的子結點都有3個,那麼會形成很大程度的浪費。

7.2 樹的鏈表(兒子-兄弟)表示法

爲了解決樹的普通鏈表表示會有空間的浪費的缺陷,咱們能夠把鏈表的指針設置兩個連接,一個連接指向兒子結點,另外一個連接指向兄弟結點,以下圖所示:

上圖所示的樹的表示方法,已經足夠完美了,可是若是咱們把鏈表表示的樹旋轉45°角,會發現以下圖所示:

通過45°角的旋轉,咱們會發現一顆二叉樹(一個結點至多擁有2個子結點的樹),也就是說最普通的樹其實能夠經過二叉樹表示,也就是說咱們只要把二叉樹研究透了,咱們即研究透了樹

相關文章
相關標籤/搜索