最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java二叉查找樹的實(shí)現(xiàn)代碼

 更新時間:2017年08月10日 11:51:37   作者:evasean  
這篇文章主要為大家詳細(xì)介紹了java二叉查找樹的實(shí)現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了java二叉查找樹的具體代碼,供大家參考,具體內(nèi)容如下

package 查找;

import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.StdOut;

public class BST<Key extends Comparable<Key>, Value> {
  private class Node {
    private Key key; // 鍵
    private Value value;// 值
    private Node left, right; // 指向子樹的鏈接
    private int n; // 以該節(jié)點(diǎn)為根的子樹中的節(jié)點(diǎn)總數(shù)

    public Node(Key key, Value val, int n) {
      this.key = key;
      this.value = val;
      this.n = n;
    }
  }

  private Node root;

  public int size() {
    return size(root);
  }

  private int size(Node x) {
    if (x == null)
      return 0;
    else
      return x.n;
  }

  /**
   * 如果樹是空的,則查找未命中 如果被查找的鍵小于根節(jié)點(diǎn),則在左子樹中繼續(xù)查找 如果被查找的鍵大于根節(jié)點(diǎn),則在右子樹中繼續(xù)查找
   * 如果被查找的鍵和根節(jié)點(diǎn)的鍵相等,查找命中
   * 
   * @param key
   * @return
   */
  public Value get(Key key) {
    return get(root, key);
  }

  private Value get(Node x, Key key) {
    if (x == null)
      return null;
    int cmp = key.compareTo(x.key);
    if (cmp < 0)
      return get(x.left, key);
    else if (cmp > 0)
      return get(x.right, key);
    else
      return x.value;
  }

  /**
   * 二叉查找樹的一個很重要的特性就是插入的實(shí)現(xiàn)難度和查找差不多。 當(dāng)查找到一個不存在與樹中的節(jié)點(diǎn)(null)時,new 新節(jié)點(diǎn),并將上一路徑指向該節(jié)點(diǎn)
   * 
   * @param key
   * @param val
   */
  public void put(Key key, Value val) {
    root = put(root, key, val);
  }

  private Node put(Node x, Key key, Value val) {
    if (x == null)
      return new Node(key, val, 1);
    int cmp = key.compareTo(x.key);
    if (cmp < 0)
      x.left = put(x.left, key, val);
    else if (cmp > 0)
      x.right = put(x.right, key, val);
    else
      x.value = val;
    x.n = size(x.left) + size(x.right); // 要及時更新節(jié)點(diǎn)的子樹數(shù)量
    return x;
  }

  public Key min() {
    return min(root).key;
  }

  private Node min(Node x) {
    if (x.left == null)
      return x;
    return min(x.left);
  }

  public Key max() {
    return max(root).key;
  }

  private Node max(Node x) {
    if (x.right == null)
      return x;
    return min(x.right);
  }

  /**
   * 向下取整:找出小于等于該鍵的最大鍵
   * 
   * @param key
   * @return
   */
  public Key floor(Key key) {
    Node x = floor(root, key);
    if (x == null)
      return null;
    else
      return x.key;
  }

  /**
   * 如果給定的鍵key小于二叉查找樹的根節(jié)點(diǎn)的鍵,那么小于等于key的最大鍵一定出現(xiàn)在根節(jié)點(diǎn)的左子樹中
   * 如果給定的鍵key大于二叉查找樹的根節(jié)點(diǎn),那么只有當(dāng)根節(jié)點(diǎn)右子樹中存在大于等于key的節(jié)點(diǎn)時,
   * 小于等于key的最大鍵才會出現(xiàn)在右子樹中,否則根節(jié)點(diǎn)就是小于等于key的最大鍵
   * 
   * @param x
   * @param key
   * @return
   */
  private Node floor(Node x, Key key) {
    if (x == null)
      return null;
    int cmp = key.compareTo(x.key);
    if (cmp == 0)
      return x;
    else if (cmp < 0)
      return floor(x.left, key);
    else {
      Node t = floor(x.right, key);
      if (t == null)
        return x;
      else
        return t;
    }
  }

  /**
   * 向上取整:找出大于等于該鍵的最小鍵
   * 
   * @param key
   * @return
   */
  public Key ceiling(Key key) {
    Node x = ceiling(root, key);
    if (x == null)
      return null;
    else
      return x.key;
  }

  /**
   * 如果給定的鍵key大于二叉查找樹的根節(jié)點(diǎn)的鍵,那么大于等于key的最小鍵一定出現(xiàn)在根節(jié)點(diǎn)的右子樹中
   * 如果給定的鍵key小于二叉查找樹的根節(jié)點(diǎn),那么只有當(dāng)根節(jié)點(diǎn)左子樹中存在大于等于key的節(jié)點(diǎn)時,
   * 大于等于key的最小鍵才會出現(xiàn)在左子樹中,否則根節(jié)點(diǎn)就是大于等于key的最小鍵
   * 
   * @param x
   * @param key
   * @return
   */
  private Node ceiling(Node x, Key key) {
    if (x == null)
      return null;
    int cmp = key.compareTo(x.key);
    if (cmp == 0)
      return x;
    else if (cmp > 0) {
      return ceiling(x.right, key);
    } else {
      Node t = floor(x.left, key);
      if (t == null)
        return x;
      else
        return t;
    }
  }

  /**
   * 選擇排名為k的節(jié)點(diǎn)
   * 
   * @param k
   * @return
   */
  public Key select(int k) {
    return select(root, k).key;
  }

  private Node select(Node x, int k) {
    if (x == null)
      return null;
    int t = size(x.left);
    if (t > k)
      return select(x.left, k);
    else if (t < k)
      return select(x.right, k - t - 1);// 根節(jié)點(diǎn)也要排除掉
    else
      return x;
  }

  /**
   * 查找給定鍵值的排名
   * 
   * @param key
   * @return
   */
  public int rank(Key key) {
    return rank(key, root);
  }

  private int rank(Key key, Node x) {
    if (x == null)
      return 0;
    int cmp = key.compareTo(x.key);
    if (cmp < 0)
      return rank(key, x.left);
    else if (cmp > 0)
      return 1 + size(x.left) + rank(key, x.right);
    else
      return size(x.left);
  }
  /**
   * 刪除最小鍵值對
   */
  public void deleteMin(){
    root = deleteMin(root);
  }
  /**
   * 不斷深入根節(jié)點(diǎn)的左子樹直到遇見一個空鏈接,然后將指向該節(jié)點(diǎn)的鏈接指向該結(jié)點(diǎn)的右子樹
   * 此時已經(jīng)沒有任何鏈接指向要被刪除的結(jié)點(diǎn),因此它會被垃圾收集器清理掉
   * @param x
   * @return
   */
  private Node deleteMin(Node x){
    if(x.left == null) return x.right;
    x.left = deleteMin(x.left);
    x.n = size(x.left)+size(x.right) + 1;
    return x;
  }
  
  public void deleteMax(){
    root = deleteMax(root);
  }
  private Node deleteMax(Node x){
    if(x.right == null ) return x.left;
    x.right = deleteMax(x.right);
    x.n = size(x.left)+size(x.right) + 1;
    return x;
  }
  
  public void delete(Key key){
    root = delete(root,key);
  }
  private Node delete(Node x, Key key){
    if(x == null) return null;
    int cmp = key.compareTo(x.key);
    if(cmp < 0) x.left = delete(x.left,key);
    else if(cmp > 0) x.right = delete(x.right,key);
    else{
      if(x.right == null) return x.left;
      if(x.left == null ) return x.right;
      /**
       * 如果被刪除節(jié)點(diǎn)有兩個子樹,將被刪除節(jié)點(diǎn)暫記為t
       * 從t的右子樹中選取最小的節(jié)點(diǎn)x,將這個節(jié)點(diǎn)x的左子樹設(shè)為t的左子樹
       * 這個節(jié)點(diǎn)x的右子樹設(shè)為t的右子樹中刪除了最小節(jié)點(diǎn)的子樹,這樣就成功替換了t的位置
       */
      Node t = x;
      x = min(t.right);
      x.left = t.left;
      x.right = deleteMin(t.right);
    }
    x.n = size(x.left) + size(x.right) +1;
    return x;
  }
  
  public void print(){
    print(root);
  }
  private void print(Node x){
    if(x == null ) return;
    print(x.left);
    StdOut.println(x.key);
    print(x.right);
  }
  
  public Iterable<Key> keys(){
    return keys(min(),max());
  }
  public Iterable<Key> keys(Key lo, Key hi){
    Queue<Key> queue = new Queue<Key>();
    keys(root, queue, lo, hi);
    return queue;
  }
  private void keys(Node x, Queue<Key> queue, Key lo, Key hi){
    if(x == null) return;
    int cmplo = lo.compareTo(x.key);
    int cmphi = lo.compareTo(x.key);
    if(cmplo < 0 ) keys(x.left,queue,lo,hi);
    if(cmplo <= 0 && cmphi >= 0) queue.enqueue(x.key);
    if(cmphi > 0 ) keys(x.right,queue,lo,hi);
  }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java創(chuàng)建多線程服務(wù)器流程

    Java創(chuàng)建多線程服務(wù)器流程

    這篇文章主要介紹了Java創(chuàng)建多線程服務(wù)器流程,以下實(shí)例演示了如何使用Socket類的accept()方法和ServerSocket類的MultiThreadServer(socketname)方法來實(shí)現(xiàn)多線程服務(wù)器程序
    2023-05-05
  • struts中動態(tài)方法調(diào)用使用通配符

    struts中動態(tài)方法調(diào)用使用通配符

    這篇文章主要介紹了struts中動態(tài)方法調(diào)用使用通配符的相關(guān)資料,非常不錯,具有參考借鑒價值,感興趣的朋友一起看看吧
    2016-09-09
  • springboot連接neo4j報錯的解決方案

    springboot連接neo4j報錯的解決方案

    這篇文章主要介紹了springboot連接neo4j報錯的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Spring底層原理由淺入深探究

    Spring底層原理由淺入深探究

    Spring事務(wù)有可能會提交,回滾、掛起、恢復(fù),所以Spring事務(wù)提供了一種機(jī)制,可以讓程序員來監(jiān)聽當(dāng)前Spring事務(wù)所處于的狀態(tài),這篇文章主要介紹了Spring底層事務(wù)原理,需要的朋友可以參考下
    2023-02-02
  • 談?wù)劄镴AXB和response設(shè)置編碼,解決wechat4j中文亂碼的問題

    談?wù)劄镴AXB和response設(shè)置編碼,解決wechat4j中文亂碼的問題

    中文亂碼是每個程序員都會遇到的問題,本篇文章主要介紹了談?wù)劄镴AXB和response設(shè)置編碼,解決wechat4j中文亂碼的問題,具有一定的參考價值,有興趣的可以了解一下。
    2016-12-12
  • 基于jdk動態(tài)代理和cglib動態(tài)代理實(shí)現(xiàn)及區(qū)別說明

    基于jdk動態(tài)代理和cglib動態(tài)代理實(shí)現(xiàn)及區(qū)別說明

    這篇文章主要介紹了基于jdk動態(tài)代理和cglib動態(tài)代理實(shí)現(xiàn)及區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Spring Boot整合SSE實(shí)時通信的問題小結(jié)

    Spring Boot整合SSE實(shí)時通信的問題小結(jié)

    本文介紹了服務(wù)器發(fā)送事件(Server-Sent Events,SSE)技術(shù),其主要特點(diǎn)包括單向數(shù)據(jù)流、自動重連、自定義事件類型等,SSE適用于實(shí)時更新場景,如新聞推送、評論系統(tǒng)等,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • 詳解Redis 緩存 + Spring 的集成示例

    詳解Redis 緩存 + Spring 的集成示例

    本篇文章主要介紹了Redis 緩存 + Spring 的集成示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • java中的?HashMap?的加載因子是0.75原理探討

    java中的?HashMap?的加載因子是0.75原理探討

    在Java中,HashMap是一種常用的數(shù)據(jù)結(jié)構(gòu),用于存儲鍵值對,它的設(shè)計目標(biāo)是提供高效的插入、查找和刪除操作,在HashMap的實(shí)現(xiàn)中,加載因子(Load?Factor)是一個重要的概念,本文將探討為什么Java中的HashMap的加載因子被設(shè)置為0.75
    2023-10-10
  • java中Map集合的常用方法總結(jié)大全

    java中Map集合的常用方法總結(jié)大全

    開發(fā)中最常用的就是List集合和Map集合,Map集合是基于java核心類java.util中的,下面這篇文章主要給大家總結(jié)介紹了關(guān)于java中Map集合的一些常用方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01

最新評論

南开区| 凌海市| 邹平县| 庆云县| 房山区| 连平县| 德令哈市| 玉门市| 兰溪市| 鹿泉市| 社旗县| 类乌齐县| 平南县| 陇西县| 白银市| 沂源县| 中牟县| 湘阴县| 南部县| 临沧市| 札达县| 额敏县| 罗城| 晋中市| 敖汉旗| 石楼县| 晋城| 化德县| 永和县| 石嘴山市| 大厂| 扎囊县| 章丘市| 绥中县| 兴仁县| 遂溪县| 成武县| 福泉市| 锡林浩特市| 铁力市| 丹巴县|