二叉連結串列(鏈式二叉樹)的非遞迴建立
這裡我採用的是先序非遞迴建立二叉樹。思路很簡單:
首先要有一個結點陣列。
1.取第一個結點,是否為空,不是就作為樹根,壓棧,是空則樹根為空,結束。
2.取下一個結點a。
3.取棧頂結點b,如果棧頂結點沒有左孩子,那麼b->lchild=a,如果棧頂結點b有左孩子沒有右孩子,那麼 b->rchild=a,如果棧頂結點左孩子右孩子都存在,那麼彈棧,重複3。
4.重複2-4,直到棧空,或者所有結點都被加入樹中。
那麼問題來了,怎麼判斷棧頂結點是否存在左孩子和右孩子呢。比較簡單的想法就是增設一個標誌位,藉助標誌位來判斷。不過在寫樹的時候,顯然還是希望每個結點不要多出來一些奇怪的變數,只在建樹的時候有用,其它地方都沒有用處。那麼是否可以通過左右孩子指標域的值來判斷呢,答案是肯定的。我們可以在建立每個結點的時候將這些左右孩子指標回指自身,以此來代表這些結點的左右孩子是否存在,操作易於實現,判斷起來也很方便。
下貼程式碼:
我這裡假設每個結點都用一個字元來代表,’#’就代表這個結點為空。然後這一串字元就構成了串 nodes,作為函式的輸入。當然可以改變這種方式,讀者只需稍作修改。
#include <iostream>
#include <string>
#include <stack>
using namespace std;
typedef struct BiTreeNode{
char ch;
BiTreeNode *lchild;
BiTreeNode *rchild;
}BiTreeNode,*BiTree;
BiTreeNode* CreateTree(string nodes){//構造二叉連結串列的函式
//先序非遞迴法構造鏈式二叉樹
stack<BiTreeNode*> stack1;
BiTreeNode *pd1,*pd2;//指向二叉樹結點的指標
bool flag;
int n=nodes.size();
BiTreeNode *root=NULL;
if(nodes[0]!='#'){//不是空樹
pd1=new BiTreeNode;
pd1->lchild=pd1;//左孩子指標回指
pd1->rchild=pd1;//右孩子指標回指
pd1->ch=nodes[0];
root=pd1;
int k=0;
stack1.push(pd1);//樹根入棧
while(!stack1.empty()&&k!=n-1){
flag=false;
if(nodes[++k]!='#'){
pd2=new BiTreeNode;
pd2->ch=nodes[k];
pd2->lchild=pd2;//左孩子指標回指
pd2->rchild=pd2;//右孩子指標回指
flag=true;
}else
pd2=NULL;
pd1=stack1.top();
while(pd1->lchild!=pd1&&pd1->rchild!=pd1){//找到沒有左右孩子的棧頂結點
stack1.pop();
pd1=stack1.top();
}
if(pd1->lchild==pd1)//沒有左孩子
pd1->lchild=pd2;
else
pd1->rchild=pd2;
if(flag)//pd2不是空指標
stack1.push(pd2);//pd2入棧
}
}
return root;
}
void preordertraverse(BiTree T){//先序遍歷
if(T){
cout << T->ch;
preordertraverse(T->lchild);
preordertraverse(T->rchild);
}
}
void inordertraverse(BiTree T){//中序遍歷
if(T){
inordertraverse(T->lchild);
cout << T->ch;
inordertraverse(T->rchild);
}
}
int main(){
string nodes;
cin >> nodes;
BiTree T=CreateTree(nodes);
preordertraverse(T);//先序遍歷
cout << endl;
inordertraverse(T);//中序遍歷
cout << endl;
return 0;
}
附一張執行結果圖:
輸入:AB#DF###C#E##
輸出:
原本我打算將樹寫成一個模板類,在寫建構函式時發現,雖然遞迴建立樹很簡潔,但是寫在建構函式裡很不方便,於是自己在紙上畫圖,想出了這個演算法。其中恐有訛誤,如果發現請聯絡作者指正。
相關推薦
二叉連結串列(鏈式二叉樹)的非遞迴建立
這裡我採用的是先序非遞迴建立二叉樹。思路很簡單: 首先要有一個結點陣列。 1.取第一個結點,是否為空,不是就作為樹根,壓棧,是空則樹根為空,結束。 2.取下一個結點a。 3.取棧頂結
連結串列(鏈式儲存)的基本操作
Clist.h #ifndef CLIST_H_ #define CLIST_H_ typedef struct _tag_CListNode {struct _tag_CListNode* next; }CListNode; typedef void CList; CLi
連結串列、鏈式棧、鏈式佇列、二叉樹的C簡要實現
/*單鏈表簡要實現 * * */ #include <stdio.h> #include <stdlib.h> struct Node; typedef struct
UVa 122 Trees on the level(鏈式二叉樹的建立和層次遍歷)
構建 void target .net color 鏈接 struct failed div 題目鏈接: https://cn.vjudge.net/problem/UVA-122 1 /* 2 問題 3 給出每個節點的權值和路線,輸出該二叉樹的層次遍歷序列。
玩轉二叉連結串列 (20 分)
玩轉二叉連結串列 (20 分) 先序建立二叉樹的二叉連結串列 設計程式,按先序建立二叉樹的二叉連結串列;然後先序、中序、後序遍歷二叉樹。 輸入格式: 按先序輸入一棵二叉樹。二叉樹中每個結點的鍵值用字元表示,字元之間不含空格。注意空樹資訊也要提供,以#字元表示空樹。 輸出格式:
二叉樹採用二叉連結串列儲存,複製二叉樹的演算法(樹的應用)
二叉樹採用二叉連結串列儲存,試寫出複製一棵二叉樹的演算法。 話不多說上程式碼: #include<stdio.h> #include<stdlib.h> typedef struct BiTnode { &
LeetCode-114.二叉樹展開為連結串列(相關話題:深度優先)
給定一個二叉樹,原地將它展開為連結串列。 例如,給定二叉樹 1 / \ 2 5 / \ \ 3 4 6 將其展開為: 1 \ 2 \ 3 \ 4 \ 5
c語言實現二叉樹(二叉連結串列)非遞迴後序遍歷
演算法思想 因為後序遍歷是先訪問左子樹,再訪問右子樹,最後訪問根節點。當用棧實現遍歷時,必須分清返回根節點時,是從左子樹返回的還是從右子樹返回的。所以使用輔助指標r指向最近已訪問的結點。當然也可以在節點中增加一個標誌域,記錄是否已被訪問。 #include<iost
擴充套件的先序遍歷序列建立以二叉連結串列方式儲存的二叉樹,後序遍歷
1. 請根據使用者輸入的“擴充套件的先序遍歷序列”(用小圓點表示空子樹),建立以二叉連結串列方式儲存的二叉樹,然後寫出後序遍歷該二叉樹的非遞迴演算法,並將對應的程式除錯執行通過。 #include<stdio.h> #include<std
二叉樹,非遞迴實現(前序、中序、後序)
一、結合棧的方式實現,先讓右孩子入棧,再讓左孩子入棧。棧為空後,結束遍歷。 標頭檔案.根據具體的函式名自己建立,另外需要使用棧,引用棧的標頭檔案 stack.h # pragma oncee # include<stdio.h> # include<s
二叉樹的非遞迴遍歷(先序、中序、後序和層序遍歷)
[前文] 二叉樹的非遞迴遍歷有 先序遍歷、中序遍歷 、後續遍歷 和 層序遍歷。 非遞迴演算法實現的基本思路:使用堆疊。而層序遍歷的實現:使用佇列。 如下圖所示的二叉樹: 前序遍歷順序為:ABCDE (先訪問根節點,然後先序遍歷其左子樹,最後先序遍歷
C語言 二叉樹的遍歷 遞迴和(多種)非遞迴演算法
//二叉樹遍歷 //作者:nuaazdh //時間:2011年12月1日 #include<stdio.h> #include<stdlib.h> #define OK 1 #define ERROR 0 #defi
二叉樹的非遞迴遍歷(前序中序後序非遞迴C語言)
前兩天做資料結構實驗,要求用非遞迴演算法遍歷二叉樹。只知道用棧來儲存資料,具體演算法還不太清楚。經過兩天的搜尋,看到網上很多種解法,很多解法都是用C++來寫的演算法,一直找不到用C語言寫的演算法,所以就總結了一下,用C寫出了一個遍歷二叉樹的三種非遞迴演算法。 前
LeetCode題解-144. Binary Tree Preorder Traversal(二叉樹的非遞迴前序遍歷)
題目:Given a binary tree, return the preorder traversal of its nodes' values.Example:Input: [1,null,2,3] 1 \ 2 / 3 Outpu
二叉樹的非遞迴遍歷 (leetcode)
利用資料結構-棧,佇列, 加上相應思路等完成。 leetcode練習,隔段時間敲幾次程式碼 非遞迴先序 #include <cstdlib> #include <iostream> #includ
隊列(鏈式存儲結構)
eat 結構 int type logs nsh com body tps 隊列的鏈式存儲結構不常用 同理,實際上也可以用一個單鏈表實現 插入、刪除分別在鏈表兩頭進行,即插入在表尾(rear),刪除在表頭(front) 圖解如下: 0、結構初始化 struct Lis
棧(鏈式存儲結構)
特性 null while raw 分享 leet source strlen http 堆棧:具有一定操作約束的線性表,只能在一端作插入、刪除 具有後入先出的特性(Last In First Out) 分順序存儲結構、鏈式存儲結構兩種形式 堆棧的順序存儲結構 通常
LeetCode 25. k個一組翻轉連結串列(Reverse Nodes in k-Group)
題目描述 給出一個連結串列,每 k 個節點一組進行翻轉,並返回翻轉後的連結串列。 k 是一個正整數,它的值小於或等於連結串列的長度。如果節點總數不是 k 的整數倍,那麼將最後剩餘節點保持原有順序。 示例 : 給定這個連結串列:1->
資料結構 樹筆記-6 二叉樹的非遞迴先序遍歷
如下這棵二叉樹的先序遍歷結果為:ABDEFPC 針對於上面的這棵二叉樹,結合程式碼,講述遍歷過程: #include <stdio.h>#include <malloc.h> //#define ElemType
資料結構 樹筆記-7 二叉樹的非遞迴中序遍歷
二叉樹的 非遞迴 中序遍歷 //#define ElemType char typedef char ElemType; 結點中存放的資料的型別的定義