二叉树的递归遍历和层序遍历(c/c++)
- 遞歸遍歷:
二叉樹的三種遞歸遍歷為先序遍歷,中序遍歷和后續(xù)遍歷。它們相似之處在于都是對(duì)二叉樹的遞歸遍歷且對(duì)任何一個(gè)結(jié)點(diǎn)都經(jīng)過三次,區(qū)別之處在于哪一次對(duì)該結(jié)點(diǎn)進(jìn)行訪問,由此分為先,中,后序遍歷。所以對(duì)于任一結(jié)點(diǎn)都有:三次經(jīng)過,一次訪問。
先序遍歷:
僅以先序遍歷為例說明其思路。
當(dāng)我們對(duì)二叉樹進(jìn)行遍歷時(shí),先對(duì)該結(jié)點(diǎn)內(nèi)的數(shù)據(jù)進(jìn)行訪問,然后依次遍歷它的左右孩子結(jié)點(diǎn),遞歸進(jìn)行直至結(jié)束。
例:對(duì)一個(gè)有三個(gè)結(jié)點(diǎn)的二叉樹,包含根結(jié)點(diǎn)A,左孩子結(jié)點(diǎn)B和右孩子結(jié)點(diǎn)C。先序遍歷的函數(shù)執(zhí)行過程如下:(下面的字母和數(shù)字表示函數(shù)的執(zhí)行步驟)
第一次函數(shù)調(diào)用:A,訪問根結(jié)點(diǎn)中的數(shù)據(jù),遞歸調(diào)用左孩子結(jié)點(diǎn)B,遞歸調(diào)用右孩子結(jié)點(diǎn)C。
第二次函數(shù)調(diào)用左孩子結(jié)點(diǎn) B:訪問左孩子結(jié)點(diǎn)內(nèi)的數(shù)據(jù),遞歸調(diào)用左孩子結(jié)點(diǎn)的左孩子結(jié)點(diǎn)B->left,遞歸調(diào)用左孩子結(jié)點(diǎn)的右孩子結(jié)點(diǎn)B->right。
第三次函數(shù)調(diào)用左孩子的左孩子結(jié)點(diǎn)B->left:該結(jié)點(diǎn)為空,不執(zhí)行。返回第二次函數(shù)調(diào)用。
第四次函數(shù)調(diào)用左孩子的右孩子結(jié)點(diǎn)B->right:該結(jié)點(diǎn)為空,不執(zhí)行。返回第二次函數(shù)調(diào)用。第二次函數(shù)調(diào)用執(zhí)行完畢,返回第一次函數(shù)調(diào)用中。
第五次函數(shù)調(diào)用右孩子結(jié)點(diǎn) C:訪問右孩子結(jié)點(diǎn)內(nèi)數(shù)據(jù),遞歸調(diào)用右孩子結(jié)點(diǎn)的左孩子結(jié)點(diǎn)C->left,遞歸調(diào)用右孩子結(jié)點(diǎn)的右孩子結(jié)點(diǎn)C->right。
第六次函數(shù)調(diào)用右孩子的左孩子結(jié)點(diǎn)C->left:該結(jié)點(diǎn)為空,不執(zhí)行。返回第五次函數(shù)調(diào)用。
第七次函數(shù)調(diào)用右孩子的右孩子結(jié)點(diǎn)C->right:該結(jié)點(diǎn)為空,不執(zhí)行。返回第五次函數(shù)調(diào)用。第五次函數(shù)調(diào)用執(zhí)行完畢,返回第一次函數(shù)調(diào)用。
第一次函數(shù)調(diào)用執(zhí)行完畢。遞歸結(jié)束。
void preorder(btNode* p) {if (p != NULL){visit(p);preorder(p->lc);preorder(p->rc);} }中序遍歷:
void inorder(btNode* p) {if (p != NULL){inorder(p->lc);visit(p);inorder(p->rc);} }后序遍歷:
void postorder(btNode* p) {if (p != NULL){postorder(p->lc);postorder(p->rc);visit(p);} }對(duì)于下圖中的樹:
先序遍歷結(jié)果為:ABDECF ? 根 ? 左 ? 右
中序遍歷結(jié)果為:DBEAFC ? 左 ? 根 ? 右
后序遍歷結(jié)果為:DEBFCA ? 左 ? 右 ? 根
中序與先(后)序可唯一確定一顆二叉樹。
- 層序遍歷:
二叉樹的層序遍歷的實(shí)現(xiàn)思路:
建立一個(gè)輔助數(shù)據(jù)結(jié)構(gòu)隊(duì)列,在此采用大小為10的循環(huán)隊(duì)列。初始先將二叉樹根節(jié)點(diǎn)入隊(duì),從而使得隊(duì)列不為空,接下來進(jìn)入到循環(huán)中,當(dāng)隊(duì)列不為空時(shí),隊(duì)列中元素出隊(duì),訪問出隊(duì)元素中的數(shù)據(jù),并在出隊(duì)時(shí)將其左右孩子挨個(gè)入隊(duì),每出隊(duì)一個(gè)結(jié)點(diǎn),將其左右孩子分別入隊(duì),直至隊(duì)列為空,此時(shí)所有結(jié)點(diǎn)都被訪問過了。
void level(btNode* p) {int front, rear;front = rear = 0;btNode* que[10];//構(gòu)造一個(gè)大小為10的簡單循環(huán)隊(duì)列if (p != NULL){rear = (rear + 1) % 10;que[rear] = p;while (rear != front){front = (front + 1) % 10;std::cout << que[front]->data << ' ';//出隊(duì)時(shí)進(jìn)行輸出或進(jìn)行操作if (que[front]->lc != NULL){rear = (rear + 1) % 10;que[rear] = que[front]->lc;}if (que[front]->rc != NULL){rear = (rear + 1) % 10;que[rear] = que[front]->rc;}}} }關(guān)于樹的遍歷完整代碼如下:
#include<iostream> typedef struct btNode {char data;//結(jié)點(diǎn)中的信息struct btNode* lc;//左孩子結(jié)點(diǎn)struct btNode* rc;//右孩子結(jié)點(diǎn) }btNode;btNode* initial(char* ele, int num);//用數(shù)組初始化一棵樹(默認(rèn)創(chuàng)建一棵完全二叉樹) void preorder(btNode* p);//先序遍歷 void inorder(btNode* p);//中序遍歷 void postorder(btNode* p);//后續(xù)遍歷 void level(btNode* p);//層序遍歷 int main() {using namespace std;char data[6] = { 'a', 'b', 'c', 'd', 'e', 'f' };btNode* p = initial(data, 6);cout << "先序遍歷: ";preorder(p);cout << endl;cout << "中序遍歷: ";inorder(p);cout << endl;cout << "后序遍歷: ";postorder(p);cout << endl;cout << "層序遍歷: ";level(p);cout << endl;return 0; } btNode* initial(char* ele, int num) {if (num<1)return NULL;btNode* temp = new btNode[num];int i = 0;while (i < num)//將所有結(jié)點(diǎn)的左右子樹置為空{(diào)temp[i].lc = NULL;temp[i].rc = NULL;++i;}i = 0;while (i < num/2)//通過完全二叉樹的順序存儲(chǔ)來創(chuàng)建樹的結(jié)構(gòu){if (2*i+1<num)temp[i].lc = temp + 2 * i + 1;if (2*i+2<num)temp[i].rc = temp + 2 * i + 2;++i;}for (i = 0; i < num; i++)//對(duì)樹中的每個(gè)結(jié)點(diǎn)賦值temp[i].data = ele[i];return temp; } void preorder(btNode* p) {if (p != NULL){std::cout << p->data << ' ';preorder(p->lc);preorder(p->rc);} } void inorder(btNode* p) {if (p != NULL){inorder(p->lc);std::cout << p->data << ' ';inorder(p->rc);} } void postorder(btNode* p) {if (p != NULL){postorder(p->lc);postorder(p->rc);std::cout << p->data << ' ';} } void level(btNode* p) {int front, rear;front = rear = 0;btNode* que[10];if (p != NULL){rear = (rear + 1) % 10;que[rear] = p;while (rear != front){front = (front + 1) % 10;std::cout << que[front]->data << ' ';if (que[front]->lc != NULL){rear = (rear + 1) % 10;que[rear] = que[front]->lc;}if (que[front]->rc != NULL){rear = (rear + 1) % 10;que[rear] = que[front]->rc;}}} }其中數(shù)組中的輸入為下圖中的樹:
程序的輸出結(jié)果為:
二叉樹非遞歸遍歷可參考:
二叉樹的非遞歸遍歷(c/c++)_Little_ant_的博客-CSDN博客
總結(jié)
以上是生活随笔為你收集整理的二叉树的递归遍历和层序遍历(c/c++)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 树与二叉树(c/c++)
- 下一篇: 二叉树的非递归遍历(c/c++)