二叉樹遍歷的基本操作:建立、銷燬;層序遍歷
阿新 • • 發佈:2018-11-13
一、簡單的建立、銷燬
.h
# pragma once # include<assert.h> # include<malloc.h> # include<stdio.h> # include<stdlib.h> # include<string.h> typedef char DataType; typedef struct BinTreeNode { struct BinTreeNode* _pLeft; struct BinTreeNode* _pRight; DataType _data; }Node,*PNode; PNode BuyBinTreeNode(DataType data); void _CreateBinTree(PNode* pRoot, DataType array[], int size, int* index, DataType invalid); void CreateBinTree(PNode* pRoot, DataType array[], int size, DataType invalid); //拷貝一棵樹,根加左子樹加右子樹 PNode CopyBinTree(PNode pRoot); //二叉樹的前需遍歷:根+左子樹+右子樹 void PreOrder(PNode pRoot); //中序遍歷:左子樹+根節點+右子樹 void InOrder(PNode pRoot); //後序遍歷:左子樹+右子樹+根節點 void PostOrder(PNode pRoot); void DestroyBinTree(PNode* pRoot);
.c
# include"BinaryTree.h" # pragma once # include<assert.h> # include<malloc.h> # include<stdio.h> # include<stdlib.h> # include<string.h> PNode BuyBinTreeNode(DataType data) { PNode pNewNode = (PNode)malloc(sizeof(Node)); if (NULL == pNewNode) { assert(0); return NULL; } pNewNode->_data = data; pNewNode->_pLeft = NULL; pNewNode->_pRight = NULL; return pNewNode; } void _CreateBinTree(PNode* pRoot, DataType array[], int size, int* index, DataType invalid) { assert(pRoot);//此時pRoot代表外部實參的地址,可以改變指向 assert(index); if (*index < size&&invalid != array[*index]){ *pRoot = BuyBinTreeNode(array[*index]); //建立根節點的左子樹 ++(*index); _CreateBinTree(&(*pRoot)->_pLeft, array, size, index, invalid); //建立根節點的右子樹 ++(*index); _CreateBinTree(&(*pRoot)->_pRight, array, size, index, invalid); } } void CreateBinTree(PNode* pRoot, DataType array[], int size, DataType invalid) { int index = 0; _CreateBinTree(pRoot, array, size, &index, invalid); } //拷貝一棵樹,根加左子樹加右子樹 PNode CopyBinTree(PNode pRoot){ PNode pNewRoot = NULL; if (pRoot){ //拷貝根節點 pNewRoot = BuyBinTreeNode(pRoot->_data); //拷貝根節點的左子樹 if (pRoot->_pLeft) pNewRoot->_pLeft = CopyBinTree(pRoot->_pLeft); //拷貝根節點的右子樹 if (pRoot->_pRight) pNewRoot->_pRight = CopyBinTree(pRoot->_pRight); } return pNewRoot; } //二叉樹的前需遍歷:根+左子樹+右子樹 void PreOrder(PNode pRoot) { if (pRoot) { printf("%c ", pRoot->_data); PreOrder(pRoot->_pLeft); PreOrder(pRoot->_pRight); } } //中序遍歷:左子樹+根節點+右子樹 void InOrder(PNode pRoot) { if (pRoot) { InOrder(pRoot->_pLeft); printf("%c ", pRoot->_data); InOrder(pRoot->_pRight); } } //後序遍歷:左子樹+右子樹+根節點 void PostOrder(PNode pRoot) { if (pRoot) { PostOrder(pRoot->_pLeft); PostOrder(pRoot->_pRight); printf("%c ", pRoot->_data); } } void DestroyBinTree(PNode* pRoot) { assert(pRoot); if (*pRoot){ //銷燬左子樹 DestroyBinTree(&(*pRoot)->_pLeft); //銷燬右子樹 DestroyBinTree(&(*pRoot)->_pRight); //銷燬根節點 free(*pRoot); *pRoot = NULL; } } void TestBinTree() { char* str = "ABD###CE##F"; PNode pRoot = NULL, pNewRoot; CreateBinTree(&pRoot, str, strlen(str), '#'); pNewRoot = CopyBinTree(pRoot); printf("前序遍歷:"); PreOrder(pRoot); printf("\n"); printf("中序遍歷:"); InOrder(pRoot); printf("\n"); printf("後序遍歷:"); PostOrder(pRoot); printf("\n"); } //A B D # # # C E #
test.c
# include"Tree.h"
int main()
{
TestBinTree();
system("pause");
return 0;
}
結果:
二、層序遍歷1、將當前節點遍歷後,並且儲存起來(加到佇列中去)
.h
# pragma once # include<assert.h> # include<malloc.h> # include<stdio.h> # include<stdlib.h> # include<string.h> # include"Queue.h" typedef char BTDataType; typedef struct BinTreeBTNode { struct BinTreeBTNode* _pLeft; struct BinTreeBTNode* _pRight; BTDataType _data; }BTNode,*PBTNode; PBTNode BuyBinTreeBTNode(BTDataType data); void _CreateBinTree(PBTNode* pRoot, BTDataType array[], int size, int* index, BTDataType invalid); void CreateBinTree(PBTNode* pRoot, BTDataType array[], int size, BTDataType invalid); //拷貝一棵樹,根加左子樹加右子樹 PBTNode CopyBinTree(PBTNode pRoot); //二叉樹的前需遍歷:根+左子樹+右子樹 void PreOrder(PBTNode pRoot); //中序遍歷:左子樹+根節點+右子樹 void InOrder(PBTNode pRoot); //後序遍歷:左子樹+右子樹+根節點 void PostOrder(PBTNode pRoot);
queue.h
# pragma once
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# include<assert.h>
//實現鏈式佇列的以下操作:
//typedef int DataType
extern struct BTNode;//相當於把型別在檔案中聲明瞭
//聲明後,編譯器檢測後發現有這種型別的存在。
//這種型別是存在的,沒在當前檔案中進行了定義,可能在其他的檔案中進行了定義
//連結的時候直接到其他檔案中去找,找到了即可,沒找到就會報錯
typedef struct BTNode* DataType;
typedef struct Node
{
DataType _data;
struct Node* _pNext;
}Node, *PNode;
typedef struct Queue
{
PNode _pHead;
PNode _pTail;
}Queue;
// 佇列的初始化
void QueueInit(Queue* q);
// 入佇列
void QueuePush(Queue* q, DataType data);
// 出佇列
void QueuePop(Queue* q);
// 取隊頭元素
DataType QueueFront(Queue* q);
// 取隊尾元素
DataType QueueBack(Queue* q);
// 獲取佇列中元素的個數
int QueueSize(Queue* q);
// 檢測佇列是否為空
int QueueEmpty(Queue* q);
PNode BuyNode(DataType data)
{
PNode pNewNode = (PNode)malloc(sizeof(Node));
if (NULL == pNewNode)
{
assert(0);
return NULL;
}
pNewNode->_data = data;
pNewNode->_pNext = NULL;
return pNewNode;
}
.c
# include"BinaryTree.h"
//#define NULL 0
PBTNode BuyBinTreeNode(DataType data)
{
PBTNode pNewNode = (PBTNode)malloc(sizeof(Node));
if (NULL == pNewNode)
{
assert(0);
return NULL;
}
pNewNode->_data = data;
pNewNode->_pLeft = NULL;
pNewNode->_pRight = NULL;
return pNewNode;
}
void _CreateBinTree(PBTNode* pRoot, DataType array[], int size, int* index, DataType invalid)
{
assert(pRoot);//此時pRoot代表外部實參的地址,可以改變指向
assert(index);
if (*index < size&&invalid != array[*index]){
*pRoot = BuyBinTreeNode(array[*index]);
//建立根節點的左子樹
++(*index);
_CreateBinTree(&(*pRoot)->_pLeft, array, size, index, invalid);
//建立根節點的右子樹
++(*index);
_CreateBinTree(&(*pRoot)->_pRight, array, size, index, invalid);
}
}
void CreateBinTree(PBTNode* pRoot, DataType array[], int size, DataType invalid)
{
int index = 0;
_CreateBinTree(pRoot, array, size, &index, invalid);
}
//拷貝一棵樹,根加左子樹加右子樹
PBTNode CopyBinTree(PBTNode pRoot){
PBTNode pNewRoot = NULL;
if (pRoot){
//拷貝根節點
pNewRoot = BuyBinTreeNode(pRoot->_data);
//拷貝根節點的左子樹
if (pRoot->_pLeft)
pNewRoot->_pLeft = CopyBinTree(pRoot->_pLeft);
//拷貝根節點的右子樹
if (pRoot->_pRight)
pNewRoot->_pRight = CopyBinTree(pRoot->_pRight);
}
return pNewRoot;
}
//二叉樹的前需遍歷:根+左子樹+右子樹
void PreOrder(PBTNode pRoot)
{
if (pRoot)
{
printf("%c ", pRoot->_data);
PreOrder(pRoot->_pLeft);
PreOrder(pRoot->_pRight);
}
}
//中序遍歷:左子樹+根節點+右子樹
void InOrder(PBTNode pRoot)
{
if (pRoot)
{
InOrder(pRoot->_pLeft);
printf("%c ", pRoot->_data);
InOrder(pRoot->_pRight);
}
}
//後序遍歷:左子樹+右子樹+根節點
void PostOrder(PBTNode pRoot)
{
if (pRoot)
{
PostOrder(pRoot->_pLeft);
PostOrder(pRoot->_pRight);
printf("%c ", pRoot->_data);
}
}
void LevelOrder(PBTNode pRoot)
{
Queue q;
if (NULL == pRoot)
return;
QueueInit(&q);//初始化根節點
//把根節點的地址加到樹裡面
QueuePush(&q, pRoot);
while (!QueueEmpty(&q)){
//遍歷
PBTNode pCur = QueueFront(&q);
printf("%c ", pCur->_data);
//QueuePop(&q);出佇列的操作也可以放在這個位置上
//把元素放到佇列裡
if (pCur->_pLeft)
QueuePush(&q, pCur->_pLeft);
if (pCur->_pRight)
QueuePush(&q, pCur->_pRight);
//從佇列裡面拿出去
QueuePop(&q);
}
}
void DestroyBinTree(PBTNode* pRoot)
{
assert(pRoot);
if (*pRoot){
//銷燬左子樹
DestroyBinTree(&(*pRoot)->_pLeft);
//銷燬右子樹
DestroyBinTree(&(*pRoot)->_pRight);
//銷燬根節點
free(*pRoot);
*pRoot = NULL;
}
}
void TestBinTree()
{
char* str = "ABD###CE##F";
PBTNode pRoot = NULL, pNewRoot;
CreateBinTree(&pRoot, str, strlen(str), '#');
pNewRoot = CopyBinTree(pRoot);
printf("前序遍歷:");
PreOrder(pRoot);
printf("\n");
printf("中序遍歷:");
InOrder(pRoot);
printf("\n");
printf("後序遍歷:");
PostOrder(pRoot);
printf("\n");
printf("層序遍歷:");
LevelOrder(pRoot);
}
//A B D # # # C E #
test.c
# include"BinaryTree.h"
int main()
{
TestBinTree();
system("pause");
return 0;
}