從零開始學數據結構和算法(四)哈希表的思想和二叉樹入門

哈希表

特色

  • 數組(順序表):尋址容易
  • 鏈表:插入與刪除容易
  • 哈希表:尋址容易,插入刪除也容易的數據結構

HashTable

  • 哈希表(HashTable, 也叫散列表)css

    是根據關鍵碼值(Key value)而直接進行訪問的數據結構,它經過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。java

  • 關鍵碼值(Key value)也能夠當成是key的hash值node

    這個映射函數叫作散列函數數組

  • 存放記錄的數組叫作散列表微信

HashTable 例子

slb.jpg

  • Key : {14, 19, 5, 7, 21, 1, 13, 0, 18} 散列表: 大小爲13 的數組 a[13]; 散列函數: f(x) = x mod 13;數據結構

  • hashtable 須要自定義的內容函數

    散列函數與散列表大小 hash 衝突的解決方案 裝填因子:爲何須要這個值?由於數據越接近數組最大值,可能產生衝突的狀況就越多post

缺點

  • 擴容須要大量的空間和性能

應用

  • 電話號碼、字典、點歌系統、QQ、微信的好友等

設計(拉鍊法)

  • JDK 1.8 之前

llsj.jpg

  • JDK 1.8 開始性能

    當鏈表長度超過閾值,就轉成紅黑樹this

    hhs.jpg

什麼是樹

smss.jpg

sdgn.jpg

樹的概念

節點與樹的度

  • 結點擁有的子樹數稱爲結點的度。 度爲0的結點稱爲葉子結點或終端結點,度不爲0的結點稱爲非終端結點或分支結點。 除根結點之外,分支結點也稱爲內部結點。 樹的度是樹內各結點的度的最大值。

jdysdsd.jpg

層次和深度

sdsd.jpg

sdsd2.jpg

森林

sl.jpg

樹的存儲結構

雙親表示法

sqbsf.jpg

孩子表示法

hzbsf.jpg

雙親孩子表示法

  • 把每一個結點的孩子結點排列起來,以單鏈表做爲存儲結構, 則n個結點有n個孩子鏈表,若是是葉子結點則此單鏈表爲空, 而後n個頭指針又組成一個線性表,採用順序存儲結構,存放在一個一維數組中

sqhzbsf.jpg

孩子兄弟表示法

  • 孩子兄弟表示法爲每一個節點設計三個域: 一個數據域,一個該節點的第一個孩子節點域,一個該節點的下一個節點的兄弟指針域

hzxdbsf.jpg

二叉樹

ecsgnt.jpg

概念

ecstc.jpg

斜樹

xs.jpg

滿二叉樹

mecs.jpg

徹底二叉樹

wqecs2.jpg

定義:

  • 若設二叉樹的深度爲h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第 h 層全部的結點都連續集中在最左邊,這就是徹底二叉樹。

    徹底二叉樹是由滿二叉樹而引出來的。對於深度爲K的,有n個結點的二叉樹,當且僅當其每個結點都與深度爲K的滿二叉樹中編號從1至n的結點一一對應時稱之爲徹底二叉樹。

    1. 全部的葉結點都出如今第k層或k-l層(層次最大的兩層)
    2. 對任一結點,若是其右子樹的最大層次爲L,則其左子樹的最大層次爲L或L+l。

    一棵二叉樹至多隻有最下面的兩層上的結點的度數能夠小於2,而且最下層上的結點都集中在該層最左邊的若干位置上,則此二叉樹成爲徹底二叉樹,而且最下層上的結點都集中在該層最左邊的若干位置上,而在最後一層上,右邊的若干結點缺失的二叉樹,則此二叉樹成爲徹底二叉樹。

二叉樹的存儲結構

順序存儲

ecssx.jpg

鏈式存儲

lscc.jpg

二叉樹的遍歷

前序 ( DLR )

  • 規則是若二叉樹爲空,則空操做返回,不然先訪問跟結點,而後前序遍歷左子樹,再前序遍歷右子樹

qx.jpg

中序 ( LDR )

  • 規則是若樹爲空,則空操做返回,不然從根結點開始(注意並非先訪問根結點), 中序遍歷根結點的左子樹,而後是訪問根結點,最後中序遍歷右子樹

zx.jpg

後續 ( LRD )

  • 規則是若樹爲空,則空操做返回,不然從左到右先葉子後結點的方式遍歷訪問左右子樹,最後是訪問根結點

hx.jpg

二叉樹簡單代碼實現

public class BinarayTree {

    Node<String> root;

    public BinarayTree(String data){

        root=new Node<>(data,null,null);

    }

    public void createTree(){

        Node<String> nodeB=new Node<String>("B",null,null);

        Node<String> nodeC=new Node<String>("C",null,null);

        Node<String> nodeD=new Node<String>("D",null,null);

        Node<String> nodeE=new Node<String>("E",null,null);

        Node<String> nodeF=new Node<String>("F",null,null);

        Node<String> nodeG=new Node<String>("G",null,null);

        Node<String> nodeH=new Node<String>("H",null,null);

        Node<String> nodeJ=new Node<String>("J",null,null);

        Node<String> nodeI=new Node<String>("I",null,null);

        root.leftChild=nodeB;

        root.rightChild=nodeC;

        nodeB.leftChild=nodeD;

        nodeC.leftChild=nodeE;

        nodeC.rightChild=nodeF;

        nodeD.leftChild=nodeG;

        nodeD.rightChild=nodeH;

        nodeE.rightChild=nodeJ;

        nodeH.leftChild=nodeI;


}

/** * 中序訪問樹的全部節點 */
public void midOrderTraverse(Node root){//邏輯
    if(root==null){
        return;
    }
    midOrderTraverse(root.leftChild);//邏輯
    System.out.println("mid:"+root.data);//輸出
    midOrderTraverse(root.rightChild);//邏輯
}
/** * 前序訪問樹的全部節點 Arrays.sort(); */
public void preOrderTraverse(Node root){
    if(root==null){
        return;
    }
    System.out.println("pre:"+root.data);
    preOrderTraverse(root.leftChild);
    preOrderTraverse(root.rightChild);
}
/** * 後序訪問樹的全部節點 */
public void postOrderTraverse(Node root){
    if(root==null){
        return;
    }
    postOrderTraverse(root.leftChild);
    postOrderTraverse(root.rightChild);
    System.out.println("post:"+root.data);
}
/** * 節點 */
public class Node<T>{
    T data;
    Node<T> leftChild;
    Node<T> rightChild;

    public Node(T data, Node<T> leftChild, Node<T> rightChild) {
        this.data = data;
        this.leftChild = leftChild;
        this.rightChild = rightChild;
    }
}
}
複製代碼
相關文章
相關標籤/搜索