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

通過先序遍歷和中序遍歷后的序列還原二叉樹(實(shí)現(xiàn)方法)

 更新時(shí)間:2017年06月03日 09:32:16   投稿:jingxian  
下面小編就為大家?guī)硪黄ㄟ^先序遍歷和中序遍歷后的序列還原二叉樹(實(shí)現(xiàn)方法)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

當(dāng)我們有一個(gè)

先序遍歷序列:1,3,7,9,5,11

中序遍歷序列:9,7,3,1,5,11

我們可以很輕松的用筆寫出對應(yīng)的二叉樹。但是用代碼又該如何實(shí)現(xiàn)?

下面我們來簡單談?wù)劵舅枷搿?/p>

首先,先序遍歷的順序是根據(jù) 根-左孩子-右孩子 的順序遍歷的,那么我們可以率先確認(rèn)的是先序遍歷序列的第一個(gè)數(shù)就是根節(jié)點(diǎn),然后中序遍歷是根據(jù) 左孩子-根-右孩子 的順序遍歷的。我們通過先序遍歷確認(rèn)了根節(jié)點(diǎn),那么我們只需要在中序遍歷中找到根節(jié)點(diǎn)的位置,然后就可以很好地區(qū)分出,那些屬于左子樹的節(jié)點(diǎn),那些是屬于右子樹的節(jié)點(diǎn)了。如下圖:

我們確定數(shù)字1為根節(jié)點(diǎn),然后根據(jù)中序遍歷的遍歷順序確定,中序遍歷序列中數(shù)字1的左邊全部為左子樹節(jié)點(diǎn),右邊全部為右子樹。通過左子樹節(jié)點(diǎn)的個(gè)數(shù),得出先序遍歷序列中從根節(jié)點(diǎn)往后的連續(xù)3個(gè)數(shù)是屬于左子樹的,剩下的為右子樹。這樣再在左右子樹的序列中重復(fù)以上步驟,最終找到?jīng)]有子節(jié)點(diǎn)為止。

實(shí)現(xiàn)代碼如下:

package com.tree.traverse;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Caijh
 *
 * 2017年6月2日 下午7:21:10
 */

public class BuildTreePreOrderInOrder {

  /** 
   *       1 
   *       / \
   *      3  5 
   *      /   \
   *     7    11
   *    / 
   *   9    
   */ 
  public static int treeNode = 0;//記錄先序遍歷節(jié)點(diǎn)的個(gè)數(shù)
  private List<Node> nodeList = new ArrayList<>();//層次遍歷節(jié)點(diǎn)的隊(duì)列
  public static void main(String[] args) {
    BuildTreePreOrderInOrder build = new BuildTreePreOrderInOrder();
    int[] preOrder = { 1, 3, 7, 9, 5, 11};
    int[] inOrder = { 9, 7, 3, 1, 5, 11};
    
    treeNode = preOrder.length;//初始化二叉樹的節(jié)點(diǎn)數(shù)
    Node root = build.buildTreePreOrderInOrder(preOrder, 0, preOrder.length - 1, inOrder, 0, preOrder.length - 1);
    System.out.print("先序遍歷:");
    build.preOrder(root);
    System.out.print("\n中序遍歷:");
    build.inOrder(root);
    System.out.print("\n原二叉樹:\n");
    build.prototypeTree(root);
  }

  /**
   * 分治法
   * 通過先序遍歷結(jié)果和中序遍歷結(jié)果還原二叉樹
   * @param preOrder  先序遍歷結(jié)果序列
   * @param preOrderBegin   先序遍歷起始位置下標(biāo)
   * @param preOrderEnd  先序遍歷末尾位置下標(biāo)
   * @param inOrder  中序遍歷結(jié)果序列
   * @param inOrderBegin  中序遍歷起始位置下標(biāo)
   * @param inOrderEnd   中序遍歷末尾位置下標(biāo)
   * @return
   */
  public Node buildTreePreOrderInOrder(int[] preOrder, int preOrderBegin, int preOrderEnd, int[] inOrder, int inOrderBegin, int inOrderEnd) {
    if (preOrderBegin > preOrderEnd || inOrderBegin > inOrderEnd) {
      return null;
    }
    int rootData = preOrder[preOrderBegin];//先序遍歷的第一個(gè)字符為當(dāng)前序列根節(jié)點(diǎn)
    Node head = new Node(rootData);
    int divider = findIndexInArray(inOrder, rootData, inOrderBegin, inOrderEnd);//找打中序遍歷結(jié)果集中根節(jié)點(diǎn)的位置
    int offSet = divider - inOrderBegin - 1;//計(jì)算左子樹共有幾個(gè)節(jié)點(diǎn),節(jié)點(diǎn)數(shù)減一,為數(shù)組偏移量
    Node left = buildTreePreOrderInOrder(preOrder, preOrderBegin + 1, preOrderBegin + 1 + offSet, inOrder, inOrderBegin,inOrderBegin + offSet);
    Node right = buildTreePreOrderInOrder(preOrder, preOrderBegin + offSet + 2, preOrderEnd, inOrder, divider + 1, inOrderEnd);
    head.left = left;
    head.right = right;
    return head;
  }
  /**
   * 通過先序遍歷找到的rootData根節(jié)點(diǎn),在中序遍歷結(jié)果中區(qū)分出:中左子樹和右子樹
   * @param inOrder  中序遍歷的結(jié)果數(shù)組
   * @param rootData  根節(jié)點(diǎn)位置
   * @param begin  中序遍歷結(jié)果數(shù)組起始位置下標(biāo)
   * @param end  中序遍歷結(jié)果數(shù)組末尾位置下標(biāo)
   * @return return中序遍歷結(jié)果數(shù)組中根節(jié)點(diǎn)的位置
   */
  public int findIndexInArray(int[] inOrder, int rootData, int begin, int end) {
    for (int i = begin; i <= end; i++) {
      if (inOrder[i] == rootData)
        return i;
    }
    return -1;
  }
  /**
   * 二叉樹先序遍歷結(jié)果
   * @param n
   */
  public void preOrder(Node n) {
    if (n != null) {
      System.out.print(n.val + ",");
      preOrder(n.left);
      preOrder(n.right);
    }
  }
  /**
   * 二叉樹中序遍歷結(jié)果
   * @param n
   */
  public void inOrder(Node n) {
    if (n != null) {
      inOrder(n.left);
      System.out.print(n.val + ",");
      inOrder(n.right);
    }
  }
  /**
   * 還原后的二叉樹
   * 二叉數(shù)層次遍歷
   * 基本思想:
   *   1.因?yàn)橥茖?dǎo)出來的二叉樹是保存在Node類對象的子對象里面的,(類似于c語言的結(jié)構(gòu)體)如果通過遞歸實(shí)現(xiàn)層次遍歷的話,不容易實(shí)現(xiàn)
   *   2.這里采用List隊(duì)列逐層保存Node對象節(jié)點(diǎn)的方式實(shí)現(xiàn)對二叉樹的層次遍歷輸出
   *   3.如果父節(jié)點(diǎn)的位置為i,那么子節(jié)點(diǎn)的位置為,2i 和 2i+1;依據(jù)這個(gè)規(guī)律逐層遍歷,通過保存的父節(jié)點(diǎn),找到子節(jié)點(diǎn)。并保存,不斷向下遍歷保存。
   * @param tree
   */
  public void prototypeTree(Node tree){
    //用list存儲層次遍歷的節(jié)點(diǎn)
    if(tree !=null){
      if(tree!=null)
        nodeList.add(tree);
      nodeList.add(tree.left);
      nodeList.add(tree.right);
      int count=3;
      //從第三層開始
      for(int i=3;count<treeNode;i++){
        //第i層第一個(gè)子節(jié)點(diǎn)的父節(jié)點(diǎn)的位置下標(biāo)
        int index = (int) Math.pow(2, i-1-1)-1;
        /**
         * 二叉樹的每一層節(jié)點(diǎn)數(shù)遍歷
         * 因?yàn)榈趇層的最大節(jié)點(diǎn)數(shù)為2的i-1次方個(gè),
         */
        for(int j=1;j<=Math.pow(2, i-1);){
          //計(jì)算有效的節(jié)點(diǎn)的個(gè)數(shù),和遍歷序列的總數(shù)做比較,作為判斷循環(huán)結(jié)束的標(biāo)志
          if(nodeList.get(index).left!=null)
            count++;
          if(nodeList.get(index).right!=null)
            count++;
          nodeList.add(nodeList.get(index).left);
          nodeList.add(nodeList.get(index).right);
          index++;
          if(count>=treeNode)//當(dāng)所有有效節(jié)點(diǎn)都遍歷到了就結(jié)束遍歷
            break;
          j+=2;//每次存儲兩個(gè)子節(jié)點(diǎn),所以每次加2
        }
      }
      int flag=0,floor=1;
      for(Node node:nodeList){
        if(node!=null)
          System.out.print(node.val+" ");
        else
          System.out.print("# ");//#號表示空節(jié)點(diǎn)
        flag++;
        /**
         * 逐層遍歷輸出二叉樹
         * 
         */
        if(flag>=Math.pow(2, floor-1)){
          flag=0;
          floor++;
          System.out.println();
        }
      }
    }
  }
  /**
   * 內(nèi)部類
   * 1.每個(gè)Node類對象為一個(gè)節(jié)點(diǎn),
   * 2.每個(gè)節(jié)點(diǎn)包含根節(jié)點(diǎn),左子節(jié)點(diǎn)和右子節(jié)點(diǎn)
   */
  class Node {
    Node left;
    Node right;
    int val;
    public Node(int val) {
      this.val = val;
    }
  }
}

運(yùn)行結(jié)果:

最后逐層輸出二叉樹的基本思想:

* 1.因?yàn)橥茖?dǎo)出來的二叉樹是保存在Node類對象的子對象里面的,(類似于c語言的結(jié)構(gòu)體)如果通過遞歸實(shí)現(xiàn)層次遍歷的話,不容易實(shí)現(xiàn)

* 2.這里采用List隊(duì)列逐層保存Node對象節(jié)點(diǎn)的方式實(shí)現(xiàn)對二叉樹的層次遍歷輸出

* 3.如果父節(jié)點(diǎn)的位置為i,那么子節(jié)點(diǎn)的位置為,2i 和 2i+1;依據(jù)這個(gè)規(guī)律逐層遍歷,通過保存的父節(jié)點(diǎn),找到子節(jié)點(diǎn)。并保存,不斷向下遍歷保存。

以上這篇通過先序遍歷和中序遍歷后的序列還原二叉樹(實(shí)現(xiàn)方法)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 簡述C++的復(fù)雜性

    簡述C++的復(fù)雜性

    這篇文章主要介紹了簡述C++的復(fù)雜性,幫助大家更好的理解和認(rèn)識c++編程語言,感興趣的朋友可以了解下
    2020-08-08
  • c語言調(diào)用匯編的方法

    c語言調(diào)用匯編的方法

    在此記錄一下c調(diào)用匯編的方法,匯編使用的是AT&T語法。例子很簡單,就是在給一個(gè)整數(shù)用匯編轉(zhuǎn)換成二進(jìn)制
    2013-11-11
  • C/C++獲取主機(jī)網(wǎng)卡MAC地址的三方法

    C/C++獲取主機(jī)網(wǎng)卡MAC地址的三方法

    MAC地址(Media Access Control address),又稱為物理地址或硬件地址,是網(wǎng)絡(luò)適配器(網(wǎng)卡)在制造時(shí)被分配的全球唯一的48位地址,通過獲取MAC地址可以判斷當(dāng)前主機(jī)的唯一性可以與IP地址綁定并實(shí)現(xiàn)網(wǎng)絡(luò)準(zhǔn)入控制,本文給大家介紹了使用C/C++獲取主機(jī)網(wǎng)卡MAC地址的三方法
    2023-11-11
  • C++實(shí)現(xiàn)簡單的希爾排序Shell Sort實(shí)例

    C++實(shí)現(xiàn)簡單的希爾排序Shell Sort實(shí)例

    這篇文章主要介紹了C++實(shí)現(xiàn)簡單的希爾排序Shell Sort實(shí)例,對于正在學(xué)習(xí)算法的朋友很有借鑒價(jià)值,需要的朋友可以參考下
    2014-07-07
  • c++特殊構(gòu)造函數(shù)詳解

    c++特殊構(gòu)造函數(shù)詳解

    大家好,本篇文章主要講的是c++特殊構(gòu)造函數(shù)詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • C++實(shí)現(xiàn)圖書管理系統(tǒng)課程設(shè)計(jì)

    C++實(shí)現(xiàn)圖書管理系統(tǒng)課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)圖書管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語言?auto和register關(guān)鍵字

    C語言?auto和register關(guān)鍵字

    這篇文章主要介紹了C語言?auto、register關(guān)鍵字,文章通過變量展開全文相關(guān)的詳細(xì)內(nèi)容,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-04-04
  • C語言圖文并茂詳解鏈接過程

    C語言圖文并茂詳解鏈接過程

    首先來思考一個(gè)問題:工程中的每個(gè)C語言源文件被編譯后生成的目標(biāo)文件,這些目標(biāo)文件如何生成最終的可執(zhí)行程序? 這就需要這節(jié)我們將要分析的鏈接器
    2022-04-04
  • C++探索構(gòu)造函數(shù)私有化會產(chǎn)生什么結(jié)果

    C++探索構(gòu)造函數(shù)私有化會產(chǎn)生什么結(jié)果

    C++的構(gòu)造函數(shù)的作?:初始化類對象的數(shù)據(jù)成員。即類的對象被創(chuàng)建的時(shí)候,編譯系統(tǒng)對該對象分配內(nèi)存空間,并?動調(diào)?構(gòu)造函數(shù),完成類成員的初始化。構(gòu)造函數(shù)的特點(diǎn):以類名作為函數(shù)名,?返回類型
    2022-05-05
  • C及C++?基礎(chǔ)循環(huán)示例詳解

    C及C++?基礎(chǔ)循環(huán)示例詳解

    這篇文章主要介紹了C及C++?中的循環(huán)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09

最新評論

乐山市| 兰西县| 闻喜县| 红安县| 东源县| 平山县| 莒南县| 城口县| 梅州市| 乐都县| 安义县| 双柏县| 疏勒县| 富蕴县| 垦利县| 扎鲁特旗| 合肥市| 海南省| 鹤峰县| 星座| 佛山市| 吉木萨尔县| 荔浦县| 利津县| 宁武县| 元江| 安庆市| 莱芜市| 栾川县| 桑植县| 赤水市| 兴业县| 辽中县| 济阳县| 板桥市| 茌平县| 日照市| 富裕县| 临汾市| 海门市| 绍兴县|