1. 程式人生 > >二叉樹的建立,前、中、後序遍歷以及層次遍歷

二叉樹的建立,前、中、後序遍歷以及層次遍歷

二叉樹的建立

對於二叉樹的建立,可能很多人不知道如何去初始化一個二叉樹,其實初始化二叉樹非常簡單,需要引入一個擴充套件二叉樹的概念

擴充套件二叉樹

擴充套件二叉樹:讓二叉樹的所有節點都具有左右孩子,沒有孩子的,我們手動將其填滿,例如#,即如下所示
擴充套件二叉樹
擴充套件二叉樹主要的目的是為了確定一顆二叉樹,我們都知道,只有前序加中序或者後序加中序才能確定一棵樹,但是我們同樣可以通過擴充套件二叉樹的前序確定一棵樹,即:
ABC###DE##F##

建立二叉樹程式碼

BiTree CreateTreeNode(void)
{
    char c;
    BiTree T;
    scanf("%c"
, &c); if (c == '#') { T = NULL; } else { T = (BiTree) calloc(sizeof(BiTNode), 1); T->data = c; T->lchild = CreateTreeNode(); T->rchild = CreateTreeNode(); } return T; }

二叉樹的前中後序遍歷

二叉樹的建立採用的是遞迴的方式,那麼同樣二叉樹的遍歷同樣可以採取遞迴的方式,而且簡單明瞭

前序遍歷

:若二叉樹為空,則空操作返回,否則先訪問根節點,然後前序遍歷左子樹,再前序遍歷右子樹。按照上面建立的二叉樹,則遍歷順序為:ABCDEF

中序遍歷:若二叉樹為空,則空操作返回,否則從根節點開始(不是先訪問根節點),中序遍歷根節點的左子樹,然後是訪問根節點,最後中序遍歷右子樹。按照上面建立的二叉樹,則遍歷順序為:CBAEDF

後序遍歷:若二叉樹為空,則空操作返回,否則從左到右先葉子後節點的方式先後遍歷左右子樹,最後遍歷根節點。按照上面建立的二叉樹,則遍歷順序為:CBEFDA

前中後序遍歷程式碼

void PreOrderTraverse(BiTree T)
{
    if (T == NULL
) { return; } printf("%c", T->data); PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); } void InOrderTraverse(BiTree T) { if (T == NULL) { return; } InOrderTraverse(T->lchild); printf("%c", T->data); InOrderTraverse(T->rchild); } void PostOrderTraverse(BiTree T) { if (T == NULL) { return; } PostOrderTraverse(T->lchild); PostOrderTraverse(T->rchild); printf("%c", T->data); }

二叉樹層次遍歷(佇列方式實現)

二叉樹層次遍歷,即按從上至下從左至右按層次遍歷,這個遍歷就和上面有所不同,不過採用佇列也是非常容易理解和實現的
若根節點為空,直接返回;若根節點非空,則將根節點入隊,然後,判斷佇列是否為空,若不為空,則將隊首節點出隊,訪問,並判斷其左右子節點是否為空,若不為空,則壓入佇列,然後迴圈上面操作直到佇列為空

二叉樹層次遍歷程式碼

void LevelOrderTraverse(BiTree T)
{
    QNode Tmp, tmp;
    LinkQueue Q;
    tmp.next = NULL;
    Tmp.next = NULL;
    Q.front = NULL;
    Q.rear = NULL;

    InitQueue(&Q);
    tmp.Tree = T;
    EnQueue(&Q, &tmp);  // 根節點入隊
    while (DeQueue(&Q, &Tmp)) { // 依次出隊,直到佇列為空
        printf("%c", Tmp.Tree->data);
        if (Tmp.Tree->lchild != NULL) { // 若出隊節點有左孩子,則左孩子入隊
            tmp.Tree = Tmp.Tree->lchild;
            EnQueue(&Q, &tmp);
        }
        if (Tmp.Tree->rchild != NULL) { // 若出隊節點有右孩子,則右孩子入隊
            tmp.Tree = Tmp.Tree->rchild;
            EnQueue(&Q, &tmp);
        }
    }
    FreeQueue(&Q);
}

完整程式碼


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

  > Author: xiaojunyu/LunaW
  > Mail  : [email protected]
  > Gmail : [email protected]
  > Blog  : http://blog.csdn.net/lunaw
  > Web   : http://lunaw.cn

 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define True 1
#define False 0

typedef struct BiTNode {
    int data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

BiTree CreateTreeNode(void);    // 先變為擴充套件二叉樹,前序遞迴輸入
void PreOrderTraverse(BiTree T);    // 前序遍歷,遞迴
void InOrderTraverse(BiTree T); // 中序遍歷,遞迴
void PostOrderTraverse(BiTree T);   // 後序遍歷,遞迴
void LevelOrderTraverse(BiTree T);  // 層次遍歷,佇列
void DestroyTree(BiTree T); // 銷燬樹,後序遞迴

/* 佇列 */
typedef struct QNode {
    BiTree Tree;
    struct QNode *next;
} QNode, *QueuePtr;

typedef struct Queue {
    QueuePtr front, rear;
} LinkQueue;

int IsEmpt(LinkQueue * queue);  // 判斷是否為空
int InitQueue(LinkQueue * queue);   //初始化佇列
int FreeQueue(LinkQueue * queue);   // 釋放佇列
int EnQueue(LinkQueue * queue, QueuePtr Q); // 進佇列
int DeQueue(LinkQueue * queue, QueuePtr Q); // 出佇列

int main(void)
{
    BiTree T = NULL;
    printf("請輸入擴充套件二叉樹: ");
    T = CreateTreeNode();
    printf("\n前序遍歷: ");
    PreOrderTraverse(T);
    printf("\n中序遍歷: ");
    InOrderTraverse(T);
    printf("\n後序遍歷: ");
    PostOrderTraverse(T);
    printf("\n層次遍歷: ");
    LevelOrderTraverse(T);
    DestroyTree(T);
    return 0;
}

BiTree CreateTreeNode(void)
{
    char c;
    BiTree T;
    scanf("%c", &c);
    if (c == '#') {
        T = NULL;
    } else {
        T = (BiTree) calloc(sizeof(BiTNode), 1);
        T->data = c;
        T->lchild = CreateTreeNode();
        T->rchild = CreateTreeNode();
    }
    return T;
}

void DestroyTree(BiTree T)
{
    if (T == NULL) {
        return;
    }
    DestroyTree(T->lchild);
    DestroyTree(T->rchild);
    free(T);        // 採用後序遍歷遞迴銷燬
    T = NULL;
}

void PreOrderTraverse(BiTree T)
{
    if (T == NULL) {
        return;
    }
    printf("%c", T->data);
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
}

void InOrderTraverse(BiTree T)
{
    if (T == NULL) {
        return;
    }
    InOrderTraverse(T->lchild);
    printf("%c", T->data);
    InOrderTraverse(T->rchild);
}

void PostOrderTraverse(BiTree T)
{
    if (T == NULL) {
        return;
    }
    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    printf("%c", T->data);
}

void LevelOrderTraverse(BiTree T)
{
    QNode Tmp, tmp;
    LinkQueue Q;
    tmp.next = NULL;
    Tmp.next = NULL;
    Q.front = NULL;
    Q.rear = NULL;

    InitQueue(&Q);
    tmp.Tree = T;
    EnQueue(&Q, &tmp);  // 根節點入隊
    while (DeQueue(&Q, &Tmp)) { // 依次出隊,直到佇列為空
        printf("%c", Tmp.Tree->data);
        if (Tmp.Tree->lchild != NULL) { // 若出隊節點有左孩子,則左孩子入隊
            tmp.Tree = Tmp.Tree->lchild;
            EnQueue(&Q, &tmp);
        }
        if (Tmp.Tree->rchild != NULL) { // 若出隊節點有右孩子,則右孩子入隊
            tmp.Tree = Tmp.Tree->rchild;
            EnQueue(&Q, &tmp);
        }
    }
    FreeQueue(&Q);
}

int DeQueue(LinkQueue * queue, QueuePtr Q)
{
    QueuePtr P;
    if (IsEmpt(queue)) {
        return False;
    }
    P = queue->front->next;
    memcpy(Q, P, sizeof(QNode));    // 將隊頭資料儲存
    queue->front->next = P->next;   // 隊頭下移一位
    if (queue->rear == P) { // 若隊尾是隊頭,則將隊尾指向頭節點
        queue->rear = queue->front;
    }
    free(P);
    return True;
}

int EnQueue(LinkQueue * queue, QueuePtr Q)
{
    QueuePtr S = (QueuePtr) calloc(sizeof(QNode), 1);
    memcpy(S, Q, sizeof(QNode));
    queue->rear->next = S;
    queue->rear = S;
    return 0;
}

int InitQueue(LinkQueue * queue)
{
    queue->front = (QueuePtr) calloc(sizeof(QNode), 1);
    queue->front->next = NULL;
    queue->rear = queue->front;
    return 0;
}

int IsEmpt(LinkQueue * queue)
{
    if (queue->front == NULL || queue->front == queue->rear) {
        return True;
    } else {
        return False;
    }
}

int FreeQueue(LinkQueue * queue)
{
    QueuePtr A, B;
    for (A = queue->front; A != NULL; B = A->next, free(A), A = B) ;
    return 0;
}

相關推薦

javascript實現排序最大最小值特定值查詢以及刪除節點

 函式執行時,會產生一個棧用來存放資料,當遍歷到目的節點時,操作結束以後,就會自動執行出棧操作,所以每次執行完畢指標都會自動跳回根節點。可以在開發者模式裡打斷點看到全過程。 <!DOCTYPE html> <html> <head> <me

建立輸出精講

疑問:為什麼我是無限制的輸入資料:解答:二叉樹需要有一定的規律,最起碼節點的個數需要是2的n次方減一才能構成一個樹 還有就是考慮空節點問題,葉節點的NEXT必須為空才能結束所以說必須將樹設計好 才能輸入. #include<malloc.h> // malloc

建立(類)

程式碼: #include<iostream> #include<queue> using namespace std; //建立節點 struct Tnode { char data;//資料域 Tnode *rchild;//右孩子 Tno

leetcode 第105題(從前序列構造第106題(從中序列構造)python解法(用時40ms)

leetcode 第105題(從前序與中序遍歷序列構造二叉樹) ,第106題(從中序與後序遍歷序列構造二叉樹)python解法(用時40ms) 先從105題開始: 第105題是利用前序和中序恢復二叉樹,主要還是應用遞迴的思想。 首先看一個簡單的例子,在如下樹中: 由於前序遍歷第一個

C++ 建立

#include<iostream> using namespace std; struct bitNode { char data; bitNode *lchild, *rchild

第六章作業1—--計算機17級 7-1 根據輸出先 (25 分)

7-1 根據後序和中序遍歷輸出先序遍歷 (25 分) 本題要求根據給定的一棵二叉樹的後序遍歷和中序遍歷結果,輸出該樹的先序遍歷結果。 輸入格式: 第一行給出正整數N(≤30),是樹中結點的個數。隨後兩行,每行給出N個整數,分別對應後序遍歷和中序遍歷結果,數字間以空

資料結構實驗-C語言-二叉樹建立,前、中、後序遍歷的遞迴演算法和非遞迴演算法求葉子結點數目二叉樹深度判斷二叉樹是否相似二叉樹左右子互換,二叉樹序遍歷的演算法判斷二叉樹是否是完全二叉樹

1.實驗目的 熟練掌握二叉樹的二叉連結串列儲存結構的C語言實現。掌握二叉樹的基本操作-前序、中序、後序遍歷二叉樹的三種方法。瞭解非遞迴遍歷過程中“棧”的作用和狀態,而且能靈活運用遍歷演算法實現二叉樹的其它操作。 2.實驗內容 (1)二叉樹的二叉連結串列的建立 (2)二叉樹的前、中、後

建立以及層次

二叉樹的建立 對於二叉樹的建立,可能很多人不知道如何去初始化一個二叉樹,其實初始化二叉樹非常簡單,需要引入一個擴充套件二叉樹的概念 擴充套件二叉樹 擴充套件二叉樹:讓二叉樹的所有節點都具有左右孩子,沒有孩子的,我們手動將其填滿,例如#,即如下所示 擴充套

建立求葉節點個數求節點個數

二叉樹是筆試面試中考試最頻繁的資料結構之一,主要包括,程式建立一個二叉樹,三種次序遍歷二叉樹,返回葉子節點的數目,求二叉樹節點的總數等。建立一個二叉樹節點的資料結構 typedef struct Node {int data;struct Node *left,*right

C++實現建立

看完資料結構二叉樹部分後,通過學習書上的虛擬碼以及其他人的程式碼自己動手實現了一下,採用前序方式建立一顆二叉樹,實現了前中後層四種遍歷方式。 在層序遍歷部分與前三種遍歷不同,層序遍歷採用從根節點開始從上到下逐層遍歷,所以藉助佇列來實現,開始遍歷後,將根節點先壓入佇列,然後將

已知兩個序列建立也有)

本文主要講二叉樹的建樹,具體的說就是,題目給出你二叉樹的前序和中序,你來建樹,還有一個題目是給出中序和後序來建樹 第一題:A binary tree is a finite set of vertices that is either empty or consists

建立深度

一、概念:         二叉樹遍歷:按指定的某條搜尋路徑訪問樹中每個結點,使得每個結點均被訪問一次,而且僅被訪問一次。         根節點N,按照先遍歷左子樹L再遍歷右子樹R的原則,常見的有三種:先

基礎操作 高度搜尋排序)Java實現 程式碼集合

首先,定義一個樹類Tree.java public class Tree { public TreeNode root; } 定義樹節點類TreeNode.java public class TreeNode { public TreeNode(int

實現(包括演算法)

以前沒有記筆記的習慣,結果發現曾經實現過的東西居然都忘了,現在又需要花時間去看,去寫,雖然又有所收穫,但是畢竟在走重複的路。 從今天起,開始打路標,為了以後少走回頭路:) 還請高手多指點,不勝感激! 用Java語言實現二叉樹: 1、首先定義一個二叉樹節點類:實現 1)向某個

系列——根據構建

1、根據前序和中序構建二叉樹 思路:在二叉樹的前序遍歷序列中,第一個數字總是樹的根節點的值。但在中序遍歷序列中,根節點的值在序列的中間,左子樹的節點的值位於根節點的值得左邊,而右子樹的節點的值位於根節

線索原理及線索化(Java版)

轉載原文地址:https://blog.csdn.net/UncleMing5371/article/details/54176252一、線索二叉樹原理      前面介紹二叉樹原理及特殊二叉樹文章中提到,二叉樹可以使用兩種儲存結構:順序儲存和二叉連結串列。在使用二叉連結串列

28輸入兩棵AB判斷B是不是A的子結構。(ps:我們約定空不是任意一個的子結構)

eno 技術分享 進行 結構 一個點 left courier mage new 題目描述 輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構) 思路: 1、當Tree1和Tree2都不為零的時候,才進行比較。否則直接返回fals

手動編寫AVL(平衡實現了基本的addget remove toString contains等方法

平衡二叉樹:是指一棵空樹或者是任意節點的左右孩子的高度相差絕對值小於等於1 package com.hcc.DStructure; import java.util.ArrayList; import java.util.concurrent.ArrayBlockingQ

javascript生成, 以及其

序言 最近看了些面試題, 發現大多數都會問一個問題就是JavaScript生成二叉樹, 本來想偷懶百度看看算了, 可是發現好多網站部落格的程式碼都是一樣的, 並且生成的還是平衡二叉樹………. 如果我不輸入數字你給我生成一個試試. so, 看起來只能自己搞一下了. 百度百科–平衡二

遞迴 後續【java簡單】

本文最早發表在個人部落格 http://www.xdx97.com/#/single?bid=ead7cb23-ecfa-5108-7c5b-37f8d8696cc2  胡扯:第一次接觸 前中後 遍歷,應該是在上資料結構,玩手機擡頭偶然聽說的。很長一段時間我去記它的規律又因