當前位置:首頁 » 操作系統 » 樹的遍歷三種演算法

樹的遍歷三種演算法

發布時間: 2022-07-28 04:20:56

編程中的樹的遍歷分為哪三種

先根遍歷、中根遍歷、後根遍歷

❷ 二叉樹的三種遍歷,先,中,後遍歷

二叉樹的遍歷分為以下三種:
先序遍歷:遍歷順序規則為【根左右】
中序遍歷:遍歷順序規則為【左根右】
後序遍歷:遍歷順序規則為【左右根】
什麼是【根左右】?就是先遍歷根,再遍歷左孩子,最後遍歷右孩子;
舉個例子,看下圖(圖從網上找的):
先序遍歷:ABCDEFGHK
中序遍歷:BDCAEHGKF
後序遍歷:DCBHKGFEA
以中序遍歷為例:
中序遍歷的規則是【左根右】,我們從root節點A看起;
此時A是根節點,遍歷A的左子樹;
A的左子樹存在,找到B,此時B看做根節點,遍歷B的左子樹;
B的左子樹不存在,返回B,根據【左根右】的遍歷規則,記錄B,遍歷B的右子樹;
B的右子樹存在,找到C,此時C看做根節點,遍歷C的左子樹;
C的左子樹存在,找到D,由於D是葉子節點,無左子樹,記錄D,無右子樹,返回C,根據【左根右】的遍歷規則,記錄C,遍歷C的右子樹;
C的右子樹不存在,返回B,B的右子樹遍歷完,返回A;
至此,A的左子樹遍歷完畢,根據【左根右】的遍歷規則,記錄A,遍歷A的右子樹;
A的右子樹存在,找到E,此時E看做根節點,遍歷E的左子樹;
E的左子樹不存在,返回E,根據【左根右】的遍歷規則,記錄E,遍歷E的右子樹;
E的右子樹存在,找到F,此時F看做根節點,遍歷F的左子樹;
F的左子樹存在,找到G,此時G看做根節點,遍歷G的左子樹;
G的左子樹存在,找到H,由於H是葉子節點,無左子樹,記錄H,無右子樹,返回G,根據【左根右】的遍歷規則,記錄G,遍歷G的右子樹;
G的右子樹存在,找到K,由於K是葉子節點,無左子樹,記錄K,無右子樹,返回G,根據【左根右】的遍歷規則,記錄F,遍歷F的右子樹;
F的右子樹不存在,返回F,E的右子樹遍歷完畢,返回A;
至此,A的右子樹也遍歷完畢;
最終我們得到上圖的中序遍歷為BDCAEHGKF,無非是按照遍歷規則來的;
根據「中序遍歷」的分析,相信先序遍歷和後序遍歷也可以輕松寫出~

❸ 樹的三種主要遍歷方法是什麼啊,謝謝了

分別為先根遍歷(或前序遍歷)、中根(或中序)遍歷、後根(或後序)遍歷。三種遍歷方法的定義如下:

先根遍歷 若需遍歷的二叉樹為空,執行空操作;否則,依次執行下列操作:

訪問根結點;

②先根遍歷左子樹;

③先根遍歷右子樹。

中根遍歷 若需遍歷的二叉樹為空,執行空操作,否則,依次執行下列操作:

①中根遍歷左子樹;②訪問根結點;③中根遍右子樹。

後根遍歷 若需遍歷的二叉樹為空,執行空操作,否則,依次執行下列操作:

①後根遍歷左子樹。②後根遍歷右子樹。③訪問根結點。

❹ 二叉樹的層次遍歷演算法

二叉樹的層次遍歷演算法有如下三種方法:

給定一棵二叉樹,要求進行分層遍歷,每層的節點值單獨列印一行,下圖給出事例結構:

之後大家就可以自己畫圖了,下面給出程序代碼:

[cpp] view plain

void print_by_level_3(Tree T) {

vector<tree_node_t*> vec;

vec.push_back(T);

int cur = 0;

int end = 1;

while (cur < vec.size()) {

end = vec.size();

while (cur < end) {

cout << vec[cur]->data << " ";

if (vec[cur]->lchild)

vec.push_back(vec[cur]->lchild);

if (vec[cur]->rchild)

vec.push_back(vec[cur]->rchild);

cur++;

}

cout << endl;

}

}


最後給出完成代碼的測試用例:124##57##8##3#6##

[cpp] view plain

#include<iostream>

#include<vector>

#include<deque>

using namespace std;

typedef struct tree_node_s {

char data;

struct tree_node_s *lchild;

struct tree_node_s *rchild;

}tree_node_t, *Tree;

void create_tree(Tree *T) {

char c = getchar();

if (c == '#') {

*T = NULL;

} else {

*T = (tree_node_t*)malloc(sizeof(tree_node_t));

(*T)->data = c;

create_tree(&(*T)->lchild);

create_tree(&(*T)->rchild);

}

}

void print_tree(Tree T) {

if (T) {

cout << T->data << " ";

print_tree(T->lchild);

print_tree(T->rchild);

}

}

int print_at_level(Tree T, int level) {

if (!T || level < 0)

return 0;

if (0 == level) {

cout << T->data << " ";

return 1;

}

return print_at_level(T->lchild, level - 1) + print_at_level(T->rchild, level - 1);

}

void print_by_level_1(Tree T) {

int i = 0;

for (i = 0; ; i++) {

if (!print_at_level(T, i))

break;

}

cout << endl;

}

void print_by_level_2(Tree T) {

deque<tree_node_t*> q_first, q_second;

q_first.push_back(T);

while(!q_first.empty()) {

while (!q_first.empty()) {

tree_node_t *temp = q_first.front();

q_first.pop_front();

cout << temp->data << " ";

if (temp->lchild)

q_second.push_back(temp->lchild);

if (temp->rchild)

q_second.push_back(temp->rchild);

}

cout << endl;

q_first.swap(q_second);

}

}

void print_by_level_3(Tree T) {

vector<tree_node_t*> vec;

vec.push_back(T);

int cur = 0;

int end = 1;

while (cur < vec.size()) {

end = vec.size();

while (cur < end) {

cout << vec[cur]->data << " ";

if (vec[cur]->lchild)

vec.push_back(vec[cur]->lchild);

if (vec[cur]->rchild)

vec.push_back(vec[cur]->rchild);

cur++;

}

cout << endl;

}

}

int main(int argc, char *argv[]) {

Tree T = NULL;

create_tree(&T);

print_tree(T);

cout << endl;

print_by_level_3(T);

cin.get();

cin.get();

return 0;

}

❺ 二叉樹的遍歷演算法

這里有二叉樹先序、中序、後序三種遍歷的非遞歸演算法,此三個演算法可視為標准演算法。
1.先序遍歷非遞歸演算法
#define
maxsize
100
typedef
struct
{

Bitree
Elem[maxsize];

int
top;
}SqStack;
void
PreOrderUnrec(Bitree
t)
{
SqStack
s;
StackInit(s);
p=t;
while
(p!=null
||
!StackEmpty(s))
{
while
(p!=null)
//遍歷左子樹
{
visite(p->data);
push(s,p);
p=p->lchild;
}//endwhile
if
(!StackEmpty(s))
//通過下一次循環中的內嵌while實現右子樹遍歷
{
p=pop(s);
p=p->rchild;
}//endif
}//endwhile
}//PreOrderUnrec
2.中序遍歷非遞歸演算法
#define
maxsize
100
typedef
struct
{
Bitree
Elem[maxsize];
int
top;
}SqStack;
void
InOrderUnrec(Bitree
t)
{
SqStack
s;
StackInit(s);
p=t;
while
(p!=null
||
!StackEmpty(s))
{
while
(p!=null)
//遍歷左子樹
{
push(s,p);
p=p->lchild;
}//endwhile
if
(!StackEmpty(s))
{
p=pop(s);
visite(p->data);
//訪問根結點
p=p->rchild;
//通過下一次循環實現右子樹遍歷
}//endif
}//endwhile
}//InOrderUnrec
3.後序遍歷非遞歸演算法
#define
maxsize
100
typedef
enum{L,R}
tagtype;
typedef
struct
{
Bitree
ptr;
tagtype
tag;
}stacknode;
typedef
struct
{
stacknode
Elem[maxsize];
int
top;
}SqStack;
void
PostOrderUnrec(Bitree
t)
{
SqStack
s;
stacknode
x;
StackInit(s);
p=t;
do
{
while
(p!=null)
//遍歷左子樹
{
x.ptr
=
p;
x.tag
=
L;
//標記為左子樹
push(s,x);
p=p->lchild;
}
while
(!StackEmpty(s)
&&
s.Elem[s.top].tag==R)
{
x
=
pop(s);
p
=
x.ptr;
visite(p->data);
//tag為R,表示右子樹訪問完畢,故訪問根結點
}
if
(!StackEmpty(s))
{
s.Elem[s.top].tag
=R;
//遍歷右子樹
p=s.Elem[s.top].ptr->rchild;
}
}while
(!StackEmpty(s));
}//PostOrderUnrec

❻ 樹的遍歷的定義

樹的這3種遍歷方式可遞歸地定義如下:
如果T是一棵空樹,那麼對T進行前序遍歷、中序遍歷和後序遍歷都是空操作,得到的列表為空表。
如果T是一棵單結點樹,那麼對T進行前序遍歷、中序遍歷和後序遍歷都只訪問這個結點。這個結點本身就是要得到的相應列表。
否則,設T如圖6所示,它以n為樹根,樹根的子樹從左到右依次為T1,T2,..,Tk,那麼有:
對T進行前序遍歷是先訪問樹根n,然後依次前序遍歷T1,T2,..,Tk。
對T進行中序遍歷是先中序遍歷T1,然後訪問樹根n,接著依次對T2,T3,..,Tk進行中序遍歷。
對T進行後序遍歷是先依次對T1,T2,..,Tk進行後序遍歷,最後訪問樹根n。
n
/ |
/ |
/ |
/ ... | ...
T1 T2 T3
前序遍歷和中序遍歷可形式地依次描述如下 :
三種遍歷可以形式地描述如下,其中用到了樹的ADT操作:
Procere Preorder_Traversal(v:NodeType); {前序遍歷演算法}
begin
Visite(v); {訪問節點v}
i:=Leftmost_Child(v);
while i<>∧ do
begin
Preorder_Traversal(i);{從左到右依次訪問v的每一個兒子節點i}
i:=Right_Sibling(i);
end;
end;
Procere Inorder_Traversal(v:NodeType); {中序遍歷演算法}
begin
if Leftmost_Child(v)=∧ {判斷v是否是葉節點}
then Visite(v)
else
begin
Inorder_Traversal(Leftmost_Child(v)); {中序遍歷v的左邊第一個兒子節點}
Visite(v); {訪問節點v}
i:=Right_Sibling(Leftmost_Child(v)); {i=v的左邊第二個兒子}
while i<>∧ do
begin
Inorder_Traversal(i);
{從左邊第二個開始到最右邊一個為止依次訪問v的每一個兒子節點i}
i:=Right_Sibling(i);
end;
end;
end;
Procere Postorder_Traversal(v:NodeType); {後序遍歷演算法}
begin
i:=Leftmost_Child(v);
while i<>∧ do
begin
Preorder_Traversal(i);{從左到右依次訪問v的每一個兒子節點i}
i:=Right_Sibling(i);
end;
Visite(v); {訪問節點v}
end;

❼ 遍歷的樹

樹的遍歷是樹的一種重要的運算。所謂遍歷是指對樹中所有結點的信息的訪問,即依次對樹中每個結點訪問一次且僅訪問一次。樹的3種最重要的遍歷方式分別稱為前序遍歷、中序遍歷和後序遍歷。以這3種方式遍歷一棵樹時,若按訪問結點的先後次序將結點排列起來,就可分別得到樹中所有結點的前序列表、中序列表和後序列表。相應的結點次序分別稱為結點的前序、中序和後序。 樹的這3種遍歷方式可遞歸地定義如下:
如果T是一棵空樹,那麼對T進行前序遍歷、中序遍歷和後序遍歷都是空操作,得到的列表為空表。
如果T是一棵單結點樹,那麼對T進行前序遍歷、中序遍歷和後序遍歷根,樹根的子樹從左到右依次為T1,T2,..,Tk,那麼有:
對T進行前序遍歷是先訪問樹根n,然後依次前序遍歷T1,T2,..,Tk。
對T進行中序遍歷是先中序遍歷T1,然後訪問樹根n,接著依次對T2,T2,..,Tk進行中序遍歷。
對T進行後序遍歷是先依次對T1,T2,..,Tk進行後序遍歷,最後訪問樹根n。
n
/ |
/|
/ |
/ ... | ...
T1T2T3 前序遍歷和中序遍歷可形式地依次描述如下 :
三種遍歷可以形式地描述如下,其中用到了樹的ADT操作:
Procere Preorder_Traversal(v:NodeType); {前序遍歷演算法}
begin
Visite(v); {訪問節點v}
i:=Leftmost_Child(v);
while i<>;∧ do
begin
Preorder_Traversal(i);{從左到右依次訪問v的每一個兒子節點i}
i:=Right_Sibling(i);
end;
end;
Procere Inorder_Traversal(v:NodeType); {中序遍歷演算法}
begin
if Leftmost_Child(v)=∧ {判斷v是否是葉節點}
then Visite(v)
else
begin
Inorder_Traversal(Leftmost_Child(v)); {中序遍歷v的左邊第一個兒子節點}
Visite(v); {訪問節點v}
i:=Right_Sibling(Leftmost_Child(v)); {i=v的左邊第二個兒子}
while i<>;∧ do
begin
Inorder_Traversal(i);
{從左邊第二個開始到最右邊一個為止依次訪問v的每一個兒子節點i}
i:=Right_Sibling(i);
end;
end;
end;
Procere Postorder_Traversal(v:NodeType); {後序遍歷演算法}
begin
i:=Leftmost_Child(v);
while i<>;∧ do
begin
Preorder_Traversal(i);{從左到右依次訪問v的每一個兒子節點i}
i:=Right_Sibling(i);
end;
Visite(v); {訪問節點v}
end;
為了將一棵樹中所有結點按某種次序列表,只須對樹根調用相應過程。例如對圖7中的樹進行前序遍歷、中序遍歷和後序遍歷將分別得到前序列表:A B E F I J C D G H;中序列表:E B I F J A CG D H;後序列表:E I J F B G H D C A。
下面介紹一種方法可以產生上述3種遍歷方式的結點列表。設想我們從樹根出發,依逆時針方向沿樹的外緣繞行(例如圍繞圖7中的樹繞行的路線如圖8所示)。繞行途中可能多次經過同一結點。如果我們按第一次經過的時間次序將各個結點列表,就可以得到前序列表;如果按最後一次經過的時間次序列表,也就是在即將離開某一結點走向其父親時將該結點列出,就得到後序列表。為了產生中序列表,要將葉結點與內部結點加以區別。葉結點在第一次經過時列出,而內部結點在第二次經過時列出。
在上述3種不同次序的列表方式中,各樹葉之間的相對次序是相同的,它們都按樹葉之間從左到右的次序排列。3種列表方式的差別僅在於內部結點之間以及內部結點與樹葉之間的次序有所不同。
一棵樹進行前序列表或後序列表有助於查詢結點間的祖先子孫關系。假設結點v在後序列表中的序號(整數)為postorder(v),我們稱這個整數為結點v的後序編號。例如在圖7中,結點E,I和J的後序編號分別為1,2和3。 結點的後序編號具有這樣的特點:設結點v的真子孫個數為desc(v),那麼在以v為根的子樹中的所有結點的後序編號恰好落在postorder(v)- desc(v)與postorder(v)之間。因此為了檢驗結點x是否為結點y的子孫,我們只要判斷它們的後序編號是否滿足:
postorder(y)-desc(y)≤postorder(x)≤postorder(y)
前序編號也具有類似的性質。

❽ 二叉樹前序遍歷法舉例!急急急!!!

二叉樹的三種金典遍歷法

1.前序遍歷法:

前序遍歷(DLR)

前序遍歷(DLR)

前序遍歷首先訪問根結點然後遍歷左子樹,最後遍歷右子樹。在遍歷左、右子樹時,仍然先訪問根結點,然後遍歷左子樹,最後遍歷右子樹。

若二叉樹為空則結束返回,否則:

(1)訪問根結點

(2)前序遍歷左子樹

(3)前序遍歷右子樹

注意的是:遍歷左右子樹時仍然採用前序遍歷方法。

如上圖所示二叉樹

前序遍歷,也叫先根遍歷,遍歷的順序是,根,左子樹,右子樹

遍歷結果:ABDECF

中序遍歷,也叫中根遍歷,順序是左子樹,根,右子樹

遍歷結果:DBEAFC

後序遍歷,也叫後根遍歷,遍歷順序,左子樹,右子樹,根

遍歷結果:DEBFCA

2.中序遍歷法:

中序遍歷

中序遍歷(LDR)

中序遍歷首先遍歷左子樹,然後訪問根結點,最後遍歷右子樹。在遍歷左、右子樹時,仍然先遍歷左子樹,再訪問根結點,最後遍歷右子樹。即:

若二叉樹為空則結束返回,否則:

(1)中序遍歷左子樹

(2)訪問根結點

(3)中序遍歷右子樹。

注意的是:遍歷左右子樹時仍然採用中序遍歷方法。

3.後序遍歷法:

後序遍歷

簡介

後序遍歷是二叉樹遍歷的一種。後序遍歷指在訪問根結點、遍歷左子樹與遍歷右子樹三者中,首先遍歷左子樹,然後遍歷右子樹,最後遍歷訪問根結點,在遍歷左、右子樹時,仍然先遍歷左子樹,然後遍歷右子樹,最後遍歷根結點。後序遍歷有遞歸演算法和非遞歸演算法兩種。

遞歸演算法

演算法描述:

(1)若二叉樹為空,結束

(2)後序遍歷左子樹

(3)後序遍歷右子樹

(4)訪問根結點

偽代碼

PROCEDUREPOSTRAV(BT)

IFBT<>0THEN

{

POSTRAV(L(BT))

POSTRAV(R(BT))

OUTPUTV(BT)

}

RETURN

c語言描述

structbtnode

{

intd;

structbtnode*lchild;

structbtnode*rchild;

};

voidpostrav(structbtnode*bt)

{

if(bt!=NULL)

{

postrav(bt->lchild);

postrav(bt->rchild);

printf("%d",bt->d);

}

}

非遞歸演算法

演算法1(c語言描述):

voidpostrav1(structbtnode*bt)

{

structbtnode*p;

struct

{

structbtnode*pt;

inttag;

}st[MaxSize];

}

inttop=-1;

top++;

st[top].pt=bt;

st[top].tag=1;

while(top>-1)/*棧不為空*/

{

if(st[top].tag==1)/*不能直接訪問的情況*/

{

p=st[top].pt;

top--;

if(p!=NULL)

{

top++;/*根結點*/

st[top].pt=p;

st[top].tag=0;

top++;/*右孩子結點*/

st[top].pt=p->p->rchild;

st[top].tag=1;

top++;/*左孩子結點*/

st[top].pt=p->lchild;

st[top].tag=1;

}

}

if(st[top].tag==0)/*直接訪問的情況*/

{

printf("%d",st[top].pt->d);

top--;

}

}

}

演算法2:

voidpostrav2(structbtnode*bt)

{

structbtnode*st[MaxSize],*p;

intflag,top=-1;

if(bt!=NULL)

{

do

{

while(bt!=NULL)

{

top++;

st[top]=bt;

bt=bt->lchild;

}

p=NULL;

flag=1;

while(top!=-1&&flag)

{

bt=st[top];

if(bt->rchild==p)

{

printf("%d",bt->d);

top--;

p=bt;

}

else

{

bt=bt->rchild;

flag=0;

}

}

}while(top!=-1)

printf(" ");

}

}

老曹回答必屬佳作記得給分謝謝合作!

❾ c++二叉樹的幾種遍歷演算法

遍歷二叉樹的所有結點且僅訪問一次。按照根節點位置的不同分為前序遍歷,中序遍歷,後序遍歷(除此之外還有層次遍歷,但不常用,此處不做解釋)。

1.前序遍歷:根節點->左子樹->右子樹(根節點在前面)。

2.中序遍歷:左子樹->根節點->右子樹(根節點在中間)。

3.後序遍歷:左子樹->右子樹->根節點(根節點在後邊)。

例如:求下面樹的三種遍歷:

前序遍歷:abdefgc;

中序遍歷:debgfac;

後序遍歷:edgfbca。

❿ 按照二叉樹的遞歸定義,對二叉樹遍歷的常用演算法有哪三種

前序遍歷,中序遍歷,後序遍歷。

熱點內容
php怎麼反編譯 發布:2025-01-19 14:10:54 瀏覽:590
加密貨幣交易平台排名 發布:2025-01-19 13:58:21 瀏覽:741
紅綠燈的編程 發布:2025-01-19 13:57:37 瀏覽:113
老男孩linux教程 發布:2025-01-19 13:44:48 瀏覽:941
買車怎麼區分車配置 發布:2025-01-19 13:44:45 瀏覽:242
丟失緩存視頻 發布:2025-01-19 13:44:09 瀏覽:183
C語言tp 發布:2025-01-19 13:26:20 瀏覽:107
手機qq改變存儲位置 發布:2025-01-19 13:25:17 瀏覽:83
吃解壓海鮮 發布:2025-01-19 13:23:50 瀏覽:820
sql子表 發布:2025-01-19 13:23:11 瀏覽:334