1. 程式人生 > >二叉樹遍歷的基本操作:建立、銷燬;層序遍歷

二叉樹遍歷的基本操作:建立、銷燬;層序遍歷

一、簡單的建立、銷燬

.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;
}