今天我来分享一下有关树的一些简单应用。
首先我们需要三个头文件:tree.h queue.h stack.h
#pragma once
#include
#include
#include
typedef char DataType;
typedef struct TreeNode{
struct TreeNode *lchild;
struct TreeNode *rchild;
DataType data;
} TreeNode;
TreeNode *CreateNode(DataType data)
{
TreeNode *pRoot=(TreeNode *)malloc(sizeof(TreeNode));
pRoot->data=data;
pRoot->lchild=0;
pRoot->rchild=0;
}
TreeNode *CreatTree(DataType preOrder[], int size, int *pIndex)
{
TreeNode *pRoot = CreateNode(preOrder[*pIndex]);
if (*pIndex >= size) {
return NULL;
}
if (preOrder[*pIndex] == '#') {
*pIndex += 1;
return NULL;
}
*pIndex += 1; // 用了 1 个字符
pRoot->lchild = CreatTree(preOrder, size, pIndex);
pRoot->rchild = CreatTree(preOrder, size, pIndex);
return pRoot;
}
#pragma once
#include
#include
#include
typedef TreeNode* DataType3;
typedef struct Node{
DataType3 data;
struct Node *Next;
}Node;
typedef struct Queue{
Node *pFront;
Node *pRear;
int size;
}Queue;
//队列初始化。
void QueueInit(Queue *q)
{
assert(q);
q->pFront=q->pRear=NULL;
q->size=0;
}
//队列的入队。
void QueuePush(Queue *pq,TreeNode* data)
{
Node *pNew=(Node *)malloc(sizeof(Node));
pq->size++;
assert(pq);
pNew->data=data;
pNew->Next=NULL;
if(pq->pRear==NULL)
{
pq->pRear=pNew;
pq->pFront=pNew;
}
else{
pq->pRear->Next=pNew;
pq->pRear=pNew;
}
}
//出队
void QueuePop(Queue *pq)
{
Node *p=pq->pFront;
assert(pq);
if(pq->pFront==NULL)
{
pq->pRear=NULL;
}
else{
pq->size--;
pq->pFront=p->Next;
free(p);
}
}
//取头结点
DataType3 QueuepFront(Queue *pq)
{
assert(pq);
assert(pq->size>0);
return pq->pFront->data;
}
//求是否为空队列。1为空,0不为空。
int QueueIsEmpty(Queue *pq)
{
assert(pq);
return pq->size==0?1:0;
}
//求队列元素个数
int QueueSize(Queue *pQ)
{
return pQ->size;
}
#pragma once
#include"tree.h"
#include
#include
#include
typedef TreeNode* DataType2;
typedef struct Stack{
DataType2 array[10];
int top;
}Stack;
void StackInit(Stack *s)
{
assert(s);
s->top=0;
}
void StackPush(Stack *s,DataType2 x)
{
assert(s);
assert(s->top<100);
s->array[s->top++]=x;
}
void StackPop(Stack *s)
{
assert(s);
assert(s->top>0);
s->top--;
}
DataType2 StackTop(Stack *s)
{
assert(s);
return s->array[s->top-1];
}
//1表示空,0表示没空。
int StackIsEmpty(Stack *s)
{
assert(s);
return s->top==0?1:0;
}
接下来是基本算法:
#include"stack.h"
#include"tree.h"
#include"queue.h"
//先序递归法。
void PreOrder(TreeNode *pRoot)
{
if(pRoot==NULL) //当根节点为空时,直接返回。
{
return;
}
printf("%c",pRoot->data); //前序打印顺序为根、左子树、右子树。
PreOrder(pRoot->lchild);
PreOrder(pRoot->rchild);
}
//先序非递归法。
void PreOrderLoop(TreeNode *pRoot)
{
TreeNode *pCur=pRoot; //定义两个变量。
TreeNode *pTop=NULL;
Stack s; //定义一个栈。
StackInit(&s); //初始化栈。
while(pCur!=NULL || !(StackIsEmpty(&s)))
{
while(pCur!=NULL) //当根节点不为空时,直接打印,然后入栈,并往它的左孩子走。
{
printf("%c",pCur->data);
StackPush(&s,pCur);
pCur=pCur->lchild;
}
pTop=StackTop(&s); //出栈。
StackPop(&s); //求栈顶元素。
pCur=pTop->rchild; //在走向右孩子。
}
}
//中序递归法
void InOrder(TreeNode *pRoot)
{
if(pRoot==NULL)
{
return;
}
InOrder(pRoot->lchild); //中序打印顺序为左子树、根、右子树。
printf("%c",pRoot->data);
InOrder(pRoot->rchild);
}
//中序非递归法
void InOrderLoop(TreeNode *pRoot) //与前序差不多,只是它要先入栈,先输出左孩子,在输出根节点,最后输出右孩子。
{
TreeNode *pCur=pRoot;
TreeNode *pTop=NULL;
Stack s;
StackInit(&s);
while(pCur!=NULL || !(StackIsEmpty(&s)))
{
while(pCur!=NULL)
{
StackPush(&s,pCur);
pCur=pCur->lchild;
}
pTop=StackTop(&s);
StackPop(&s);
printf("%c",pTop->data);
pCur=pTop->rchild;
}
}
//后序递归遍历
void BackOrder(TreeNode *pRoot)
{
if(pRoot==NULL)
{
return;
}
BackOrder(pRoot->lchild); //后序先遍历左孩子,在右孩子,最后根节点。
BackOrder(pRoot->rchild);
printf("%c",pRoot->data);
}
//后序非递归遍历。
void BackOrderLoop(TreeNode *pRoot)
{
TreeNode *pCur=pRoot;
TreeNode *pTop=NULL;
TreeNode *last=NULL;
Stack s;
StackInit(&s);
while(pCur!=NULL || !(StackIsEmpty(&s)))
{
while(pCur!=NULL)
{
StackPush(&s,pCur);
pCur=pCur->lchild;
}
pTop=StackTop(&s); //以上与中序一样。
if(pTop->rchild==NULL || pTop->rchild==last) //当栈顶元素的右孩子为空,或者为已经遍历过的节点。
{
StackPop(&s); //出栈,打印,并令遍历过的节点为此时的栈顶元素,继续循环。
printf("%c",pTop->data);
last=pTop;
continue;
}
pCur=pTop->rchild; //遍历它的右孩子。
}
}
//层序遍历
void LeveOrder(TreeNode *pRoot)
{
Queue q; //定义一个队列。
TreeNode *p;
if(pRoot==NULL) //如果根节点为空,则返回。
{
return;
}
QueueInit(&q);
QueuePush(&q,pRoot); //初始化并入队。
while(QueueIsEmpty(&q)==0) //当队列不为空时
{
p=QueuepFront(&q); //求队首元素。
printf("%c ",p->data); //打印。
if(p->lchild!=NULL) //如果它的左孩子不为空,入队。
{
QueuePush(&q,p->lchild);
}
if(p->rchild!=NULL) //如果它的右孩子不为空,入队。
{
QueuePush(&q,p->rchild);
}
QueuePop(&q); //出队.
}
printf("\n");
}
然后是一些应用:
//求二叉树的深度。
int TreeHighth(TreeNode *pRoot)
{
int left; //定义两个变量。
int right;
if(pRoot==NULL) //当根节点为空时,返回0.
{
return 0;
}
if(pRoot->lchild==NULL && pRoot->rchild==NULL) //如果为叶子结点,返回1.
{
return 1;
}
left=TreeHighth(pRoot->lchild); //否则递归左右子树。
right=TreeHighth(pRoot->rchild);
return left>right?left+1:right+1; //返回大的那边的子树加1.
}
//求二叉树叶子结点个数。
int Leaves(TreeNode *pRoot)
{
if(pRoot==NULL)
{
return 0;
}
if(pRoot->lchild==NULL && pRoot->rchild==NULL)
{
return 1;
}
return Leaves(pRoot->lchild) + Leaves(pRoot->rchild); //就是返回左子树的叶子数与右子树的叶子数之和。
}
//求二叉树所有节点数
int All(TreeNode *pRoot)
{
if(pRoot==NULL)
{
return 0;
}
if(pRoot->lchild==NULL && pRoot->rchild==NULL)
{
return 1;
}
return (All(pRoot->lchild)+All(pRoot->rchild)+1); //返回左右子树之和再加1.
}
//求第k层节点个数。
int Kcount(TreeNode *pRoot,int k)
{
if(pRoot==NULL)
{
return 0;
}
if(k==1)
{
return 1;
}
return Kcount(pRoot->lchild,k-1)+Kcount(pRoot->rchild,k-1);
}
//查找二叉树上的节点。
TreeNode *Find(TreeNode *pRoot,DataType data)
{
TreeNode *p;
if(pRoot==NULL)
{
return NULL;
}
if(pRoot->data=data)
{
return pRoot;
}
p=Find(pRoot->lchild,data);
if(p!=NULL)
{
return p;
}
return Find(pRoot->rchild,data);
}
//是否是完全二叉树。1:是。0:不是。
int IsComplex(TreeNode *pRoot)
{
Queue q; //定义一个队列,并初始化。
TreeNode *p=NULL;
QueueInit(&q);
if(pRoot==NULL) //如果根节点为空返回1.
{
return 1;
}
if(pRoot->lchild==NULL && pRoot->rchild==NULL) //如果为叶子结点返回1.
{
return 1;
}
QueuePush(&q,pRoot); //先进队。
while(QueueIsEmpty(&q)==0) //当队列不为空时,取队首元素,如果为空就退出,否则入队它的左右子树。最后出队。
{
p=QueuepFront(&q);
if(p==NULL)
{
break;
}
QueuePush(&q,p->lchild);
QueuePush(&q,p->rchild);
QueuePop(&q);
}
while(QueueIsEmpty(&q)==0) //当队列不为空时,如果队首元素还是不为空,则它就不是完全二叉树。
{
p=QueuepFront(&q);
if(p!=NULL)
{
return 0;
}
QueuePop(&q);
}
return 1;
}
最后是调试程序:
int main()
{
DataType *preOrder = "ABD##G##CE##F";
int index = 0;
TreeNode *pRoot = CreatTree(preOrder, strlen(preOrder), &index);
printf("前序为:");
PreOrder(pRoot); printf("\n");
printf("中序为:");
InOrder(pRoot); printf("\n");
printf("后序为:");
BackOrder(pRoot); printf("\n");
printf("前序为:");
PreOrderLoop(pRoot);printf("\n");
printf("中序为:");
InOrderLoop(pRoot);printf("\n");
printf("后序为:");
BackOrderLoop(pRoot);printf("\n");
printf("层序为:");
LeveOrder(pRoot);printf("\n");
printf("树的高度为%d\n",TreeHighth(pRoot));
printf("二叉树的叶子结点为%d\n",Leaves(pRoot));
printf("二叉树的总结点为%d\n",All(pRoot));
printf("二叉树第K层的节点数为%d\n",Kcount(pRoot,3));
printf("%d\n",IsComplex(pRoot));
system("pause");
return 0;
}
这就是调试结果,以上就是我分享的内容,谢谢观看。