BTree.h
#ifndef AAA
#define AAA
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
typedef char DataType;
typedef struct BTreeNode
{
DataType data;
struct BTreeNode *left;
struct BTreeNode *right;
}BTreeNode;
void CreatBTree(BTreeNode **cur, DataType *str, DataType invalid, int *index);
void Preorder(BTreeNode *cur);
void Inorder(BTreeNode *cur);
void Postorder(BTreeNode *cur);
void Destroy(BTreeNode **cur);
void CpBTree(BTreeNode *cur, BTreeNode **ret);
int BTreeHight(BTreeNode *cur);
int BTreeNum(BTreeNode *cur);
int BTree(BTreeNode *cur);
int BTreeKnum(BTreeNode *cur, int K);
BTreeNode *LeftNode(BTreeNode *cur, DataType data);
BTreeNode *RightNode(BTreeNode *cur, DataType data);
BTreeNode* ParentNode(BTreeNode *cur, DataType data);
#endif
BTree.c
#include"BTree.h"
//申请一个节点
BTreeNode *BuyBTreeNode(DataType data)
{
BTreeNode *NewNode = (BTreeNode *)malloc(sizeof(BTreeNode));
if(NULL == NewNode)
{
assert(0);
}
NewNode->data = data;
NewNode->left = NULL;
NewNode->right = NULL;
return NewNode;
}
//构建树
void CreatBTree(BTreeNode **cur, DataType *str, DataType invalid, int *index)
{
BTreeNode *ret = NULL;
assert(cur&&str);
if(str[*index] && invalid != str[*index])
{
(*cur) = BuyBTreeNode(str[*index]);
(*index)++;
CreatBTree(&(*cur)->left, str, invalid , index);
if(str[*index] != '\0')
{
(*index)++;
CreatBTree(&(*cur)->right, str, invalid , index);
}
}
}
//拷贝树
void CpBTree(BTreeNode *cur, BTreeNode **ret)
{
assert(ret);
if(cur)
{
(*ret) = BuyBTreeNode(cur->data);
CpBTree(cur->left, &(*ret)->left);
CpBTree(cur->right, &(*ret)->right);
}
}
//前序遍历
void Preorder(BTreeNode *cur)
{
if(cur)
{
printf("%c",cur->data);
Preorder(cur->left);
Preorder(cur->right);
}
}
//中序
void Inorder(BTreeNode *cur)
{
if(cur)
{
Inorder(cur->left);
printf("%c",cur->data);
Inorder(cur->right);
}
}
//后序
void Postorder(BTreeNode *cur)
{
if(cur)
{
Postorder(cur->left);
Postorder(cur->right);
printf("%c",cur->data);
}
}
//销毁
void Destroy(BTreeNode **cur)
{
BTreeNode *ret = *cur;
assert(cur);
if(*cur)
{
Destroy(&ret->left);
Destroy(&ret->right);
free(ret);
ret = NULL;
}
}
//求树的节点个数
int BTreeNum(BTreeNode *cur)
{
if(cur == NULL)
return 0;
return BTreeNum(cur->left) + BTreeNum(cur->right) + 1;
}
//求树的高度
int BTreeHight(BTreeNode *cur)
{
int lefthight = 0;
int righthight = 0;
if(NULL == cur)
return 0;
lefthight = BTreeHight(cur->left);
righthight = BTreeHight(cur->right);
return lefthight > righthight ? lefthight+1 : righthight+1;
}
//叶子节点
int BTree(BTreeNode *cur)
{
if(NULL == cur)
return 0;
if(NULL == cur->left && NULL == cur->right)
return 1;
return BTree(cur->left)+BTree(cur->right);
}
//求第k层的节点
int BTreeKnum(BTreeNode *cur, int K)
{
if(NULL == cur)
return 0;
if(K == 1)
return 1;
return BTreeKnum(cur->left,K-1) + BTreeKnum(cur->right,K-1);
}
//求一个节点的左孩子
BTreeNode *LeftNode(BTreeNode *cur, DataType data)
{
BTreeNode *ret = NULL;
if(NULL == cur)
return NULL;
if(cur->data == data && cur->left != NULL)
{
return cur->left;
}
ret = LeftNode(cur->left, data);
//如果左子数找到的话,就不用进右子树找了
//如果左子数找不到的话,进入右子树找
if(ret == NULL)
ret = LeftNode(cur->right, data);
return ret;
}
//求一个节点的右孩子
BTreeNode *RightNode(BTreeNode *cur, DataType data)
{
BTreeNode *ret = NULL;
if(NULL == cur)
return NULL;
if(cur->data == data && cur->right != NULL)
{
return cur->right;
}
ret = RightNode(cur->left, data);
//如果左子数找到的话,就不用进右子树找了
//如果左子数找不到的话,进入右子树找
if(ret == NULL)
ret = RightNode(cur->right, data);
return ret;
}
//求一个节点的双亲节点
BTreeNode* ParentNode(BTreeNode *cur, DataType data)
{
BTreeNode *ret = NULL;
if(cur->data == data)
return NULL;
if(cur->left->data == data|| cur->right->data == data)
return cur;
ret = ParentNode(cur->left, data);
//如果左子数找到的话,就不用进右子树找了
//如果左子数找不到的话,进入右子树找
if(ret == NULL)
ret = ParentNode(cur->right, data);
return ret;
}
Main.c
#include"BTree.h"
void Text()
{
BTreeNode *cur = NULL;
BTreeNode *ret = NULL;
BTreeNode *e = NULL;
int hight = 0;
int num = 0;
int a = 0;
DataType str[] = "ABD###CE##F";
DataType invalid = '#';
int index = 0;
int Knum = 0;
//创建树
CreatBTree(&cur, str, invalid, &index);
//拷贝树
CpBTree(cur, &ret);
printf("前序遍历为:");
Preorder(cur);
printf("\n中序遍历为:");
Inorder(cur);
printf("\n后序遍历为:");
Postorder(cur);
if(LeftNode(cur, 'C') != NULL)
printf("\nC的左孩子为:%c", LeftNode(cur, 'C')->data);
if(RightNode(cur, 'C') != NULL)
printf("\nC的右孩子为:%c",RightNode(cur, 'C')->data);
if(ParentNode(cur, 'B'))
printf("\nB的双亲为: %c", ParentNode(cur, 'B')->data);
hight = BTreeHight(cur);
printf("\n树的高度为:%d",hight);
num = BTreeNum(cur);
printf("\n树的节点个数为:%d", num);
a = BTree(cur);
printf("\n树的叶子节点为: %d", a);
Knum = BTreeKnum(cur, 3);
printf("\n树的第K层的节点数为: %d", Knum);
Destroy(&cur);
Destroy(&ret);
}
int main()
{
Text();
return 0;
}
二叉树的一些应用
BinTree.h
#ifndef _BINTREE_
#define _BINTREE_
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef char DataType;
typedef struct BinTree
{
DataType data;
struct BinTree *left;
struct BinTree *right;
}BinTree;
#define NUMBER 20
typedef struct Stack
{
BinTree a[NUMBER];
int count;
}Stack;
typedef struct Node
{
BinTree data;
struct Node*next;
}Node;
typedef struct Queue
{
Node *Front;
Node *Back;
}Queue;
void * InitBinTree(BinTree **q, DataType *str, int *i, int size);
void PreOrder(BinTree *q);
void InOrder(BinTree *q);
void PostOrder(BinTree *q);
int BinTreeHight(BinTree *q);
int BinTreeNodeNum(BinTree *q);
int BinTreeKNodeNum(BinTree *q, int K);
void BinTreeMirror(BinTree **q);
void PreOrderNor(BinTree *root, Stack *cur);
void InOrderNor(BinTree *root, Stack *cur);
void PostOrderNor(BinTree *root, Stack *cur);
void Order(BinTree *q);
int JudjeBinTree(BinTree *q);
#endif //_BINTREE
BinTree.c
#include"BinTree.h"
//创建一个节点
BinTree *BuyTreeNode(DataType d)
{
BinTree* NewNode = (BinTree*)malloc(sizeof(BinTree));
if(NewNode == NULL)
{
printf("申请失败\n");
exit(0);
}
NewNode->data = d;
NewNode->left = NULL;
NewNode->right = NULL;
return NewNode;
}
//创建一棵二叉树
//按照前序遍历的方法
void * InitBinTree(BinTree **q, DataType *str, int *i, int size)
{
if(str[*i] != '#' && *i < size-1)
{
*q = BuyTreeNode(str[*i]);
*i += 1;
InitBinTree(&(*q)->left, str, i, size);
*i += 1;
InitBinTree(&(*q)->right, str, i, size);
}
}
//前序遍历
void PreOrder(BinTree *q)
{
if(NULL != q)
{
printf("%c ", (q)->data);
PreOrder(q->left);
PreOrder(q->right);
}
}
//栈的初始化
void StackInit(Stack *ret)
{
assert(ret);
ret->count = 0;
}
//出栈
void StackPop(Stack **cur)
{
assert(cur);
if((*cur)->count == 0)
{
printf("栈空了\n");
return ;
}
(*cur)->count--;
}
//入栈
void StackPush(Stack *cur, BinTree *data)
{
assert(cur);
(cur)->a[(cur)->count] = *data;
(cur)->count++;
}
//取栈顶的元素
BinTree* StackTopNode(Stack *cur)
{
assert(cur);
return &cur->a[cur->count-1];
}
//判断栈是否为空
int EmptyStack(Stack* cur)
{
assert(cur);
if(cur->count == 0)
return 1;
return 0;
}
////前序非递归
//先遍历树的左子树,并将遍历过程中遇到的右节点保存到栈中
//当一次遍历的左子数为空时,再从栈中取栈顶的节点,以此节点为根节点,再次遍历它的左子数
//如此反复,直到栈为空时结束
void PreOrderNor(BinTree *root, Stack *cur)
{
BinTree *ret = NULL;
assert(root);
StackInit(cur);
StackPush(cur,root);
while(!EmptyStack(cur))
{
ret = StackTopNode(cur);
StackPop(&cur);
while(ret != NULL)
{
BinTree *tmp = ret->right;
printf("%c ", ret->data);
ret = ret->left;
if(tmp != NULL)
StackPush(cur, tmp);
}
}
}
//中序遍历
void InOrder(BinTree *q)
{
if(NULL != q)
{
InOrder(q->left);
printf("%c ", (q)->data);
InOrder(q->right);
}
}
//中序遍历非递归
//先寻找根节点下的最左边的节点,
void InOrderNor(BinTree *root, Stack *cur)
{
BinTree *ret = NULL;
assert(root);
StackInit(cur);
ret = root;
while(!EmptyStack(cur) || NULL != ret)
{
while(ret)
{
StackPush(cur, ret);
ret = ret->left;
}
ret = StackTopNode(cur);
StackPop(&cur);
printf("%c ", ret->data);
ret = ret->right;
}
}
//后序遍历
void PostOrder(BinTree *q)
{
if(NULL != q)
{
PostOrder(q->left);
PostOrder(q->right);
printf("%c ", (q)->data);
}
}
//后续的非递归遍历
//首先找到最左边的节点,然后查看此节点后没有右孩子,如果有的话再找右孩子的最左边的节点,如果没有的话,遍历
//做此节点,然后做标记,记录此节点已经遍历过,重复操作,直到站空
//标记是防止重复遍历节点
void PostOrderNor(BinTree *root, Stack *cur)
{
BinTree *ret = NULL;
BinTree *last = NULL;//用来标记已经遍历过的节点
assert(root);
StackInit(cur);
ret = root;
while(!EmptyStack(cur) || ret)
{
BinTree *top = 0;
//找根节点下的最左边的节点
while(ret)
{
StackPush(cur, ret);
ret = ret->left;
}
//取出栈顶的元素
top = StackTopNode(cur);
//查看栈顶的元素是否为空,并且是否被遍历过,如果都没有的话,遍历该节点,并且更新标记
if((top->right == NULL)||(top->right->data == last->data))
{
printf("%c ",top->data);
last = top;
StackPop(&cur);
}
//如果右右孩子的话,将根节点改为该节点的右节点,并且更新标记
else
{
ret = top->right;
last = top->right;
}
}
}
Node *BuyQueueNode(BinTree d)
{
Node* NewNode = (Node*)malloc(sizeof(Node));
if(NewNode == NULL)
{
printf("申请失败\n");
exit(0);
}
NewNode->data = d;
NewNode->next = NULL;
return NewNode;
}
//入队列
void QueuePush(Queue *q, BinTree d)
{
assert(q);
if(q->Front == NULL)
{
q->Front = BuyQueueNode(d);
q->Back = q->Front;
}
else
{
q->Back->next = BuyQueueNode(d);
q->Back = q->Back->next;
}
}
//出队列
void QueuePop(Queue*q)
{
assert(q);
if(q->Front != q->Back)
{
Node*ret = q->Front;
q->Front = q->Front->next;
free(ret);
ret = NULL;
}
else
{
Node*ret = q->Front;
free(ret);
ret = NULL;
q->Front = NULL;
q->Back = NULL;
}
}
DataType QueueEmpty(Queue*q)
{
if(q->Front == NULL || q->Back == NULL)
return 1;
return 0;
}
//队头元素
BinTree QueueTopNode(Queue *q)
{
return q->Front->data;
}
//队尾元素
BinTree QueueLaterNode(Queue *q)
{
return q->Back->data;
}
//初始化队列
void QueueInit(Queue *q)
{
assert(q);
q->Back = NULL;
q->Front = NULL;
}
//层序遍历
//取出队头的元素,并遍历
//如果该元素的孩子存在的话,左右孩子入栈
//重复上面的操作,直到队列空为止
void Order(BinTree *q)
{
Queue cur = {0};
BinTree ret = {0};
BinTree *p = q;
QueueInit(&cur);
//将根节点入栈,刚开始队列为空
QueuePush(&cur,*q);
while(QueueEmpty(&cur) != 1)
{
ret = QueueTopNode(&cur);
QueuePop(&cur);
printf("%c ", ret);
//左孩子存在的话,入队列
if(ret.left != NULL)
QueuePush(&cur, *(ret.left));
//有孩子存在的话,入队列
if(ret.right != NULL)
QueuePush(&cur, *(ret.right));
}
}
//判断一棵二叉树是不是完全二叉树
//如果是完全二叉树的话,一定不会有一个节点,只有右孩子而没有左孩子
//假设有一个节点只有左孩子而没有右孩子的
int JudjeBinTree(BinTree *q)
{
Queue cur = {0};
BinTree ret = {0};
BinTree *p = q;
QueueInit(&cur);
QueuePush(&cur,*q);
while(QueueEmpty(&cur) != 1)
{
ret = QueueTopNode(&cur);
QueuePop(&cur);
//当遇到的一个节点的左右孩子都为空时,退出循环,检查剩下的节点的孩子是否为空,如果有不为空的话,代表不是完全二叉树
if(ret.left == NULL && ret.right == NULL)
{
break;
}
//当一个节点只有有孩子而没有左孩子时,一定不是完全二叉树
if(ret.left == NULL && ret.right != NULL)
{
return 0;
}
//当一个节点的左孩子不为空而右孩子为空时,此节点后面的节点的孩子都不能为空
if(ret.left != NULL && ret.right == NULL)
{
QueuePush(&cur, *(ret.left));
break;
}
printf("%c ", ret);
if(ret.left != NULL)
QueuePush(&cur, *(ret.left));
if(ret.right != NULL)
QueuePush(&cur, *(ret.right));
}
//检查剩下的节点的孩子是否为空,不为空的话,不是完全二叉树
if(!QueueEmpty(&cur))
{
ret = QueueTopNode(&cur);
QueuePop(&cur);
if(ret.left != NULL || ret.right != NULL)
return 0;
}
return 1;
}
//树的高度
int BinTreeHight(BinTree *q)
{
if(q == NULL)
return 0;
if(q->left == NULL && q->right == NULL)
return 1;
return BinTreeHight(q->left) > BinTreeHight(q->right) ? BinTreeHight(q->left)+1 : BinTreeHight(q->right)+1;
}
//求树中节点的个数
int BinTreeNodeNum(BinTree *q)
{
if(q == NULL)
return 0;
return BinTreeNodeNum(q->left) + BinTreeNodeNum(q->right)+1;
}
//求二叉树中第K层节点的个数
int BinTreeKNodeNum(BinTree *q, int K)
{
if(q == NULL)
return 0;
if(K == 1)
return 1;
return BinTreeKNodeNum(q->left, K-1) + BinTreeKNodeNum(q->right, K-1);
}
//判断一个节点是否在二叉树中
int FindNodeInBTree(BinTree *q, BinTree *pos)
{
if(q == NULL || pos == NULL)
return 0;
if(q == pos)
return 1;
return FindNodeInBTree(q->left,pos) + FindNodeInBTree(q->right, pos);
}
//交换两个指针域
void Swap(BinTree **cur, BinTree **ret)
{
BinTree *tmp = NULL;
assert(cur && ret);
tmp = *cur;
*cur = *ret;
*ret = tmp;
}
//求二叉树的镜像
void BinTreeMirror(BinTree **q)
{
if(*q != NULL)
{
Swap(&(*q)->left,&(*q)->right);
BinTreeMirror(&(*q)->left);
BinTreeMirror(&(*q)->right);
}
}
Main.c
#include"BinTree.h"
void Text()
{
int i = 0;
BinTree *q = NULL;
Stack cur = {0};
DataType str[] = "ABD###CE##F";
InitBinTree(&q, str, &i, sizeof(str)/sizeof(str[0]));
printf("前序遍历为:");
PreOrder(q);
printf("\n中序遍历为:");
InOrder(q);
printf("\n后序遍历为:");
PostOrder(q);
i = BinTreeHight(q);
i = BinTreeNodeNum(q);
i = BinTreeKNodeNum(q, 3);
//BinTreeMirror(&q);
printf("\n前序遍历为:");
PreOrderNor(q, &cur);
printf("\n中序遍历为:");
InOrderNor(q, &cur);
printf("\n后序遍历为:");
PostOrderNor(q, &cur);
printf("\n层序遍历为:");
Order(q);
i = JudjeBinTree(q);
}
int main()
{
Text();
return 0;
}