C語言二叉樹的層序遍歷
在上一篇中我記錄了二叉樹的先序,中序,後序的遞迴和非遞迴遍歷方法,這一篇會接著上一篇的,記錄二叉樹的層序遍歷方法,層序遍歷用到了佇列的資料結構,下面直接上程式碼:
1、首先是鏈佇列的資料結構定義,LinkQueue.h檔案:
#pragma once #include "BinaryTree.h" /** 鏈佇列的節點定義,包含一個數據域和下一個節點的指標 */ typedef struct QueueNode { BiTreeNode* data; struct QueueNode* next; }QueueNode; /** 鏈佇列的定義,包含隊頭和隊尾指標*/ typedef struct { QueueNode* front; QueueNode* rear; }LinkQueue; LinkQueue* InitQueue();/** 鏈佇列的初始化 */ void DestoryQueue(LinkQueue*);/** 銷燬佇列 */ void EnQueue(LinkQueue*, BiTreeNode*);/** 入隊 */ BiTreeNode* DeQueue(LinkQueue*);/** 出隊 */
2、LinkQueue.c檔案:
#include <stdio.h> #include <stdlib.h> #include "LinkQueue.h" /** 鏈佇列的初始化 */ LinkQueue* InitQueue() { LinkQueue* queue = (LinkQueue*)malloc(sizeof(LinkQueue)); if (!queue) { printf("init queue error!\n"); exit(0); } queue->front = (QueueNode*)malloc(sizeof(QueueNode)); queue->front->next = NULL; queue->rear = queue->front; return queue; } /** 鏈佇列的銷燬,注意先進去的是佇列頭,後進去的是佇列尾 */ void DestoryQueue(LinkQueue* queue) { while (queue->front) { queue->rear = queue->front->next; free(queue->front); queue->front = queue->rear; } } /** 入隊 */ void EnQueue(LinkQueue* queue, BiTreeNode* node) { QueueNode* queueNode = (QueueNode*)malloc(sizeof(QueueNode)); queueNode->data = node; queueNode->next = NULL; queue->rear->next = queueNode; queue->rear = queueNode; } /** 出隊 */ BiTreeNode* DeQueue(LinkQueue* queue) { if (queue->front == queue->rear)//佇列為空 return NULL; QueueNode* p = queue->front->next; BiTreeNode* node = p->data; queue->front = p; return node; }
3、層序遍歷的主要程式碼
void LayerOrderBiTree(struct BiTreeNode* root) { int curLayerCount = 0; //當前層中的節點數 int nextLayerCount = 0; //下一層中的節點數 struct Queue* queue = InitQueue(); EnQueue(queue, root); curLayerCount++; struct BiTreeNode* p; while (p = DeQueue(queue)) { curLayerCount--; printf("%c ", p->val); if (p->left) { EnQueue(queue, p->left); nextLayerCount++; } if (p->right) { EnQueue(queue, p->right); nextLayerCount++; } if (curLayerCount == 0)//一層已經遍歷完畢 { curLayerCount = nextLayerCount; nextLayerCount = 0; printf("\n"); } } }
4、測試程式碼
#include<stdio.h>
#include <stdlib.h>
#include "Stack.h"
void printResult(char *msg, void(*p)(BiTreeNode*), BiTreeNode* node)
{
printf("\n---------%s---------\n", msg);
p(node);
printf("\n---------%s---------\n", msg);
}
int main()
{
printf("使用先序建立二叉樹,#表示空節點,請輸入二叉樹的資料:\n");
BiTreeNode* root = CreateBinaryTree();
printResult("層序遍歷", LayerOrderBiTree, root);
return 0;
}
測試用的二叉樹如下圖:
程式碼執行結果如下圖:
下面記錄遇到的坑:
在實現佇列的出隊操作時,程式碼如下:
開始我的程式碼寫錯了,第46行寫成了QueueNode* p = queue->front,結果執行報錯,單步跟蹤後發現出隊不正確,後來檢查原來46行程式碼不對,原因是初始化佇列時,給對頭分配了記憶體空間,然後對頭跟隊尾都指向該空間,但是入隊的時候該空間是沒有用到的,就相當於建立單鏈表時帶了一個頭結點,如下圖所示:
所以出隊的時候,隊頭節點應該是queue->front->next,而不是queue->front!!!
------------------------------這裡是分割線-------------------------------
今天在網上看到一種遞迴輸出層序結果的方法,記錄如下,直接上所有程式碼:
#include<iostream>
#include<stdlib.h>
using namespace std;
typedef struct Node {
char val;
struct Node* left = NULL;
struct Node* right = NULL;
}TreeNode, *Tree;
Tree createTree() {
char c;
cin >> c;
if(c == '#') return NULL;
Tree tree = (Tree)malloc(sizeof(Tree));
tree->val = c;
tree->left = createTree();
tree->right = createTree();
return tree;
}
void preOrder(Tree tree) {
TreeNode* p = tree;
if(p) {
cout << p->val << " ";
preOrder(p->left);
preOrder(p->right);
}
}
//列印第level行的節點,有列印輸出則返回true,否則返回false
bool printLevel(Tree tree, int level) {
if(!tree || level < 0) {
return false;
}
if(level == 0) {
cout << tree->val << " ";
return true;
}
return printLevel(tree->left, level - 1) + printLevel(tree->right, level - 1);
}
//層序遍歷,當某一行沒有列印時break掉迴圈
void levelOrder(Tree tree) {
for(int i = 0; ; i++) {
if(!printLevel(tree, i)) {
break;
}
}
}
int main()
{
Tree tree = createTree();
cout << "pre order: " << endl;
preOrder(tree);
cout << "\nlevel order: " << endl;
levelOrder2(tree);
return 0;
}
所用二叉樹為:
測試結果如下圖:
遞迴的程式碼比非遞迴簡單,但是複雜度可能就沒有非遞迴那麼低了
相關推薦
資料結構實驗-C語言-二叉樹的建立,前、中、後序遍歷的遞迴演算法和非遞迴演算法,求葉子結點數目,求二叉樹深度,判斷二叉樹是否相似,求二叉樹左右子樹互換,二叉樹層序遍歷的演算法,判斷二叉樹是否是完全二叉樹
1.實驗目的 熟練掌握二叉樹的二叉連結串列儲存結構的C語言實現。掌握二叉樹的基本操作-前序、中序、後序遍歷二叉樹的三種方法。瞭解非遞迴遍歷過程中“棧”的作用和狀態,而且能靈活運用遍歷演算法實現二叉樹的其它操作。 2.實驗內容 (1)二叉樹的二叉連結串列的建立 (2)二叉樹的前、中、後
二叉樹層序遍歷的c++寫法
void LevelOrder(struct node *root)//運用佇列(注意標頭檔案引用) { queue<struct node*>q; struct node *p = root; if(p) { q
【LeetCode-面試算法經典-Java實現】【107-Binary Tree Level Order Traversal II(二叉樹層序遍歷II)】
lin -m length ret itl pub util 實現類 markdown 【107-Binary Tree Level Order Traversal II(二叉樹層序遍歷II)】 【LeetCode-面試算法經典-Java實現】【全
二叉樹層序遍歷
node res queue pop left roo 實現 nod treenode 層序遍歷:用一個隊列保存當前結點的左右孩子以實現層序遍歷,因為先訪問的結點,其左右孩子結點也要先訪問 1 void LevelOrder(TreeNode* root,vector
二叉樹層序遍歷(關鍵詞:樹/二叉樹/遍歷/層序遍歷/層次遍歷)
二叉樹層序遍歷 實現 def levelOrder(self, root): if root is None: return [] res = [] queue = [root]
二叉樹層序遍歷與獲取二叉樹深度的應用
不同於中序、前序、和後續遍歷使用棧,層序遍歷使用的是佇列! 程式碼如下: void level_order(tree_pointer ptr){ int front = rear = 0; tree_pointer queue[MAX_QUEUE_SIZE];
LeetCode102 二叉樹層序遍歷
Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level). For example: Given binary
[LeetCode] Binary Tree Level Order Traversal II 二叉樹層序遍歷之二
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). For ex
[LeetCode] Binary Tree Level Order Traversal 二叉樹層序遍歷
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). For example:Given binary tree {3,9
劍指Offer——樹:把二叉樹列印成多行(二叉樹層序遍歷)
對於二叉樹的最好的解決辦法就是遞迴。遍歷方法無外乎先序遍歷,中序遍歷,後序遍歷方法以及層序遍歷方法。這裡給大家安利一個關於樹的面試題的連結,博主walkinginthewind比較全面且詳細的介紹了二叉樹相關的面試題:對於層序遍歷,最好的方法就是用佇列記錄遍歷節點的值,按層列
Binary Tree Level Order Traversal(二叉樹層序遍歷-儲存並返回結果集)
題目描述 Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level). For example: Given
LeetCode | Binary Tree Level Order Traversal(二叉樹層序遍歷)
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). For example: Gi
LeetCode 199 Binary Tree Right Side View(二叉樹層序遍歷)
Given a binary tree, imagine yourself standing on therightside of it, return the values of the node
二叉樹層序遍歷應用之Binary Tree Right Side View
Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to b
LeetCode | Binary Tree Level Order Traversal II(二叉樹層序遍歷II)
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf
BST/二叉樹層序遍歷
利用佇列的FIFO特性來實現層序遍歷。 初始化:建立佇列q,root入隊。 只要佇列不為空:存隊首元素,把隊首元素pop出來,列印隊首元素。判斷它是否有左孩子,如果有,則左孩子入隊;判斷是否有右孩子,如果有,則右孩子入隊(先判斷左孩子再右孩子是因為這裡一層中
佇列實現二叉樹層序遍歷
//基本資料結構 template<class T> struct BinaryTreeNode { T _data; BinaryTreeNode<T>* _left;
c++實現二叉樹層序、前序創建二叉樹,遞歸非遞歸實現二叉樹遍歷
log ios cst ack ret 出棧 隊列 結點 非遞歸實現 #include <iostream> #include <cstdio> #include <stdio.h> #include <string> #i
二叉樹中序遍歷(非遞迴)演算法實現--C語言
今天繼續二叉樹的學習。 昨天寫了一遍二叉樹的先序遍歷(非遞迴)演算法,今天寫一下二叉樹的二叉樹的中序遍歷(非遞迴)演算法。中序遍歷的非遞迴演算法有兩種,但是個人覺得只要掌握一種就可以了,只要自己的邏輯清晰,會哪一種又有什麼關係呢~ 首先給出今天的二叉樹的示例圖: 程式碼如下:
二叉樹後序遍歷(遞迴與非遞迴)演算法及C語言實現
二叉樹後序遍歷的實現思想是:從根節點出發,依次遍歷各節點的左右子樹,直到當前節點左右子樹遍歷完成後,才訪問該節點元素。 圖 1 二叉樹 如圖 1 中,對此二叉樹進行後序遍歷的操作過程為: 從根節點 1 開始,遍歷該節點的左子樹(以節點 2 為根節點); 遍歷節點 2 的左子樹(以節點 4 為根