二叉树是一种重要的数据结构,关于二叉树的相关操作尤为重要,其中主要操作大概分为:建树,遍历,返回二叉树的相关参数。
其中较难的是非递归遍历二叉树,直接给出代码读者若有疑问欢迎随时指点:
#pragma once
#include "Queue.h"
#include "Stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define MAX(x,y) (x)>(y)?(x):(y)
typedef char DataType;
typedef struct TreeNode{
struct TreeNode *pLeft;
struct TreeNode *pRight;
DataType data;
}TreeNode;
//初始化
TreeNode * CreateRoot(DataType data){
TreeNode *pRoot = (TreeNode *)malloc(sizeof(TreeNode));
assert(pRoot);
pRoot->data = data;
pRoot->pLeft = NULL;
pRoot->pRight = NULL;
return pRoot;
}
//建一颗二叉树
TreeNode * CreateTree(DataType preOrder[], int size, int *pIndex){
if (*pIndex >= size){
return NULL;
}
if (preOrder[*pIndex] == '#'){
*pIndex+=1;
return NULL;
}
TreeNode *pRoot = CreateRoot(preOrder[*pIndex]);
*pIndex+=1;
pRoot->pLeft = CreateTree(preOrder, size, pIndex);
pRoot->pRight = CreateTree(preOrder, size, pIndex);
return pRoot;
}
// 前序,递归
void PreOrder(TreeNode *pRoot){
if (pRoot == NULL){
return ;
}
printf("%c ",pRoot->data);
PreOrder(pRoot->pLeft);
PreOrder(pRoot->pRight);
}
// 中序,递归
void InOrder(TreeNode *pRoot){
if (pRoot == NULL){
return;
}
InOrder(pRoot->pLeft);
printf("%c ", pRoot->data);
InOrder(pRoot->pRight);
}
// 后序,递归
void PostOrder(TreeNode *pRoot){
if (pRoot == NULL){
return;
}
PostOrder( pRoot->pLeft);
PostOrder( pRoot->pRight);
printf("%c ", pRoot->data);
}
//树的结点
int GetSize(TreeNode *pRoot){
if (pRoot == NULL){
return;
}
return GetSize(pRoot->pLeft) + GetSize(pRoot->pRight) + 1;
}
//叶子的结点
int GetLeafSize(TreeNode *pRoot){
if (pRoot == NULL){
return;
}
if (pRoot->pLeft == NULL && pRoot->pRight == NULL){
return 1;
}
return GetLeafSize(pRoot->pLeft) + GetLeafSize(pRoot->pRight);
}
//K层 叶子结点
int GetKLevelSize(TreeNode *pRoot, int k){
assert(k >= 1);
if (pRoot == NULL){
return;
}
if (k==1){
return 1;
}
return GetKLevelSize(pRoot->pLeft, k - 1) + GetKLevelSize(pRoot->pRight, k - 1);
}
// 找到,返回结点地址,否则返回 NULL
TreeNode *Find(TreeNode *pRoot, DataType data){
if (pRoot == NULL){
return;
}
if (pRoot->data == data){
return pRoot;
}
TreeNode *pFind=Find(pRoot->pLeft, data);
if (pFind != NULL){
return pFind;
}
return Find(pRoot->pRight, data);
}
// 求树的高度/深度
int GetHeight(TreeNode *pRoot){
if (pRoot == NULL){
return;
}
if (pRoot->pLeft == NULL&&pRoot->pRight == NULL){
return 1;
}
int left = GetHeight(pRoot->pLeft);
int right = GetHeight(pRoot->pRight);
return MAX((left), (right)) + 1;
}
//非递层序遍历
void LevelOrder(TreeNode *pRoot){
assert(pRoot != NULL);
Queue Queue;
TreeNode *Front;
QueueInit(&Queue);
QueuePush(&Queue, pRoot);
while (!QueueIsEmpty(&Queue)){
Front = QueueFront(&Queue);
QueuePop(&Queue);
printf("%c ", Front->data);
if (Front->pLeft != NULL){
QueuePush(&Queue, Front->pLeft);
}
if (Front->pRight != NULL){
QueuePush(&Queue, Front->pRight);
}
}
}
//判断是否为完全二叉树,是返回1,否返回0.
int IsComlelement(TreeNode *pRoot){
if (pRoot == NULL){
return 1;
}
Queue Queue;
TreeNode *Front;
QueueInit(&Queue);
QueuePush(&Queue, pRoot);
while (!QueueIsEmpty(&Queue)){
Front = QueueFront(&Queue);
QueuePop(&Queue);
if (Front == NULL){
break;
}
QueuePush(&Queue, Front->pLeft);
QueuePush(&Queue, Front->pRight);
}
while (!QueueIsEmpty(&Queue)){
Front = QueueFront(&Queue);
QueuePop(&Queue);
if (Front == NULL){
return 1;
}
return 0;
}
return;
}
//非递归前序
void PreOrder1(TreeNode *pTree)
{
assert(pTree != NULL);
Stack stack;
StackInit(&stack);
TreeNode *pcur = pTree;
TreeNode *pTop=NULL;
while (pcur != NULL || !StackIsEmpty(&stack))
{
while (pcur != NULL){
printf("%c ", pcur->data);
StackPush(&stack, pcur);
pcur = pcur->pLeft;
}
pTop = getFirst(&stack);
StackPop(&stack);
pcur = pTop->pRight;
}
}
//非递归中序
void inOrder1(TreeNode *pTree){
assert(pTree != NULL);
TreeNode* pcur = pTree;
TreeNode*Top = NULL;
Stack stack;
StackInit(&stack);
while (pcur != NULL || !StackIsEmpty(&stack)){
while (pcur !=NULL)
{
StackPush(&stack,pcur);
pcur = pcur->pLeft;
}
Top = getFirst(&stack);
StackPop(&stack);
printf("%c ", Top->data);
pcur = Top->pRight;
}
}
//非递归后序
void PosOrder1(TreeNode *pTree){
assert(pTree != NULL);
Stack stack;
StackInit(&stack);
TreeNode *cur = pTree;
TreeNode *top = NULL;
TreeNode *last = NULL;
while (cur != NULL || !StackIsEmpty(&stack))
{
while (cur!=NULL)
{
StackPush(&stack, cur);
cur = cur->pLeft;
}
top = getFirst(&stack);
if (top->pRight == NULL || top->pRight == last){
printf("%c ", top->data);
StackPop(&stack);
last = top;
}
else
{
cur = top->pRight;
}
}
}
void test(){
DataType *pinput = "ABD###CE##F";
int index = 0;
TreeNode *Tree = CreateTree(pinput, strlen(pinput), &index);
PreOrder(Tree); printf("\n");
InOrder(Tree); printf("\n");
PostOrder(Tree); printf("\n");
LevelOrder(Tree); printf("\n");
PreOrder1(Tree); printf("\n");
inOrder1(Tree); printf("\n");
PosOrder1(Tree); printf("\n");
}
由于在非递归层序遍历以及判断一棵树是否为完全二叉树时用到了队列的相关操,这里给出队列的代码,便于读者理解:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef void * QDataType;
typedef struct QNode{
QDataType data;
struct QNode *pNext;//链式存储
}QNode;
typedef struct Queue{
QNode *PFront;
QNode *PRear;
int size;
} Queue;
void QueueInit(Queue *pQ)
{
assert(pQ != NULL);
pQ ->PFront=pQ->PRear=NULL;
pQ->size = 0;
}
//入队列
void QueuePush(Queue *pQ, QDataType data){
assert(pQ != NULL);
pQ->size++;
QNode *pNewNode = (QNode*)malloc(sizeof(QNode));
pNewNode->data = data;
pNewNode->pNext = NULL;
if (pQ->PRear == NULL){
pQ->PFront = pQ->PRear = pNewNode;
return;
}
pQ->PRear->pNext = pNewNode;
pQ->PRear = pNewNode;
}
//出队列
void QueuePop(Queue *pQ){
assert(pQ->PFront);
assert(pQ->size > 0);
pQ->size--;
QNode *pOld = pQ->PFront;
pQ->PFront = pQ->PFront->pNext;
free(pOld);
if (pQ->PFront == NULL){
pQ->PRear = NULL;
}
}
QDataType QueueFront(Queue *pQ){
assert(pQ != NULL);
assert(pQ->size > 0);
return pQ->PFront->data;
}
int QueueIsEmpty(Queue *pQ)
{
return pQ->size == 0 ? 1 : 0;
}
int QueueSize(Queue *pQ)
{
return pQ->size;
}
在非递归前序、中序、后序遍历二叉树时用到了栈的相关操作,这里也一并给出:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef void * QDataType;
typedef struct QNode{
QDataType data;
struct QNode *pNext;//链式存储
}QNode;
typedef struct Queue{
QNode *PFront;
QNode *PRear;
int size;
} Queue;
void QueueInit(Queue *pQ)
{
assert(pQ != NULL);
pQ ->PFront=pQ->PRear=NULL;
pQ->size = 0;
}
//入队列
void QueuePush(Queue *pQ, QDataType data){
assert(pQ != NULL);
pQ->size++;
QNode *pNewNode = (QNode*)malloc(sizeof(QNode));
pNewNode->data = data;
pNewNode->pNext = NULL;
if (pQ->PRear == NULL){
pQ->PFront = pQ->PRear = pNewNode;
return;
}
pQ->PRear->pNext = pNewNode;
pQ->PRear = pNewNode;
}
//出队列
void QueuePop(Queue *pQ){
assert(pQ->PFront);
assert(pQ->size > 0);
pQ->size--;
QNode *pOld = pQ->PFront;
pQ->PFront = pQ->PFront->pNext;
free(pOld);
if (pQ->PFront == NULL){
pQ->PRear = NULL;
}
}
QDataType QueueFront(Queue *pQ){
assert(pQ != NULL);
assert(pQ->size > 0);
return pQ->PFront->data;
}
int QueueIsEmpty(Queue *pQ)
{
return pQ->size == 0 ? 1 : 0;
}
int QueueSize(Queue *pQ)
{
return pQ->size;
}
主函数直接使用test()用来测试:
#include "tree.h"
#include "Queue.h"
int main(){
test();
system("pause");
return 0;
}
由于二叉树的相关操作比较多,也比较重要。在写代码时会出现纰漏,若有疑问欢迎随时指教,不胜感激。