C语言实现一个二叉树

来源:互联网 发布:手机淘宝的秒杀在哪里 编辑:程序博客网 时间:2024/06/05 17:49

命名恐慌症,stack和二叉树的结点名字,函数名字有点相似,希望以后能注意这个问题

收获

typedef struct node{BiTree lchild;BiTree rchild;T data;}Node;
Node为一个类型(相当于int char),这样写是为了方便,以后写类型的时候不用写struct node

struct node{BiTree lchild;BiTree rchild;T data;}Node;
Node是一个变量,此时可以直接给Node赋值,以后写结构类型的时候还是要写成struct node。


正文

BiTree.h

/*************************************************************************> File Name: BiTree.h> Author: bairutai> Mail: bairutai@aliyun.com > Created Time: 2015年09月22日 星期二 11时40分49秒 ************************************************************************/#ifndef _BITREE_H_#define _BITREE_H_#include <stdbool.h>typedef int T;typedef struct node *BiTree;typedef struct node{BiTree lchild;BiTree rchild;T data;}Node;//初始化一个二叉树BiTree* initBiTree(Node **);//摧毁一个二叉树void DestoryBiTree(BiTree *);//判断一个二叉树是否为空bool isEmpty(BiTree);//得到一个二叉树的深度int getDepth(BiTree);//生成节点Node* MakeNode(T data, Node* lchild, Node* rchild);//先序遍历void pre_order(Node *);//中序遍历void mid_order(Node *);//后序遍历void after_order(Node *);//非递归先序遍历void pre_order_(Node *);//非递归中序遍历void mid_order_(Node *);//非递归后序遍历void after_order_(Node *);#endif

BiTree.c

/*************************************************************************  > File Name: BiTree.c  > Author: bairutai  > Mail: bairutai@aliyun.com   > Created Time: 2015年09月22日 星期二 14时23分50秒 ************************************************************************/#include<stdio.h>#include<malloc.h>#include"BiTree.h"#include"stack.h"// 制造一个空的二叉树BiTree* initBiTree(Node** root){BiTree* biTree = root;return biTree;}/* 摧毁二叉树 * 这里传入二级指针是因为,指针传递的时候,是传递了一份拷贝,这样并不能 * 改变指针的值或者操作指针(比如这个函数里面要free掉),所以这里传入二 * 级指针,可以方便的free掉指针 */void DestoryBiTree(BiTree *biTree){if (NULL == *biTree){return;}else{DestoryBiTree(&((*biTree)->lchild));DestoryBiTree(&((*biTree)->rchild));}printf("destory  %d \n", (*biTree)->data);free(*biTree);*biTree = NULL;}// 判断二叉树是否为空bool isEmpty(BiTree biTree){if (NULL == biTree){return true;}else{return false;}}// 得到二叉树深度int getDepth(BiTree biTree){int depth,ldepth,rdepth;depth = ldepth = rdepth = 0;if (NULL == biTree){return 0;}else{ldepth = getDepth(biTree->lchild);rdepth = getDepth(biTree->rchild);depth = ldepth > rdepth ? ldepth:rdepth;return depth + 1;}}// 制造二叉树结点Node* MakeNode(T data, Node *lchild, Node *rchild){Node *node =(Node*)malloc(sizeof(Node));node->data = data;node->lchild = lchild;node->rchild = rchild;return node;}// 递归前序遍历// 根->左->右void pre_order(Node *node){if (NULL == node) {return;}else {printf("%d ", node->data);pre_order(node->lchild);pre_order(node->rchild);}}// 递归中序遍历// 左->根->右void mid_order(Node *node){if (NULL == node) {return;}else {mid_order(node->lchild);printf("%d ", node->data);mid_order(node->rchild);}}// 递归后序遍历// 左->右->根void after_order(Node *node){if (NULL == node) {return;}else {after_order(node->lchild);after_order(node->rchild);printf("%d ", node->data);}}/* 非递归前序遍历 * 1)访问结点P,并将结点P入栈; * 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右子结点置为当前的结点P,循环1);若不为空,则将P的左子结点置为当前的结点P; * 3)直到P为NULL并且栈为空,则遍历结束。 */void pre_order_(Node *node){Stack *stack = InitEmptyStack();while(NULL != node || !isEmpty_(stack)){while(NULL != node){// 访问结点printf("%d ",node->data);// 入栈push(stack, node);// 左子结点直为当前结点node = node->lchild;}if(!isEmpty_(stack)){// 出栈PNode pnode = pop(stack);node = pnode->data;// 右子结点置为当前结点node = node->rchild;}}}/* 非递归中序遍历 * 1)若其左子结点不为空,则将P入栈并将P的左子结点置为当前的结点P,然后对当前结点P再进行相同的处理; * 2)若其左孩子为空,则取栈顶元素并进行出栈操作,并访问该栈顶结点,然后将当前的P置为栈顶结点的右子结点; * 3)直到P为NULL并且栈为空则遍历结束 */void mid_order_(Node *node){Stack *stack = InitEmptyStack();while(NULL != node || !isEmpty_(stack)){while(NULL != node){// 入栈push(stack, node);// 左子结点置为当前结点node = node->lchild;}if(!isEmpty_(stack)){// 出栈PNode pnode = pop(stack);node = pnode->data;// 访问栈顶结点printf("%d ",node->data);// 右子结点置为当前结点node = node->rchild;}}}/* 非递归后序遍历 * 对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左子结点的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因为其右子结点还未被访问。 * 所以接下来按照相同的规则对其右子结点进行相同的处理,当访问完其右子结点时,该结点又出现在栈顶,此时可以将其出栈并访问。 * 这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。 */void after_order_(Node *node){// 记录前一个被访问的结点Node *prenode = NULL;Stack *stack = InitEmptyStack();while(NULL != node || !isEmpty_(stack)){while(NULL != node){// 入栈push(stack, node);// 左子结点置为当前结点node = node->lchild;}// 左子结点为空时,将当前结点置为栈顶结点node = stack->head->data;// 当前结点的右子结点为空或者右子结点已经访问过,则访问该结点if(NULL == node->rchild || prenode == node->rchild){// 访问该结点printf("%d ",node->data);// 更新标记的访问过的结点prenode = node;// 出栈PNode pnode = pop(stack);// 将当前结点置为空node = pnode->data = NULL;}else{// 否则将右子结点置为当前结点node = node->rchild;}}}

stack.h

/*************************************************************************> File Name: stack.h> Author: bairutai> Mail: bairutai@aliyun.com > Created Time: 2015年09月11日 星期五 10时51分13秒 ************************************************************************/#ifndef _STACK_H_#define _STACK_H_#include <stdbool.h>#include "BiTree.h"typedef Node* L;typedef struct node_ *PNode;typedef struct node_{L data;PNode next;}Node_;typedef struct{int size;PNode head;}Stack;/*构造一个空栈*/Stack *InitEmptyStack();//摧毁一个栈void destory(Stack *);//栈头元素出栈PNode pop(Stack*);//元素入栈void push(Stack *, L);//判断是否为空栈bool isEmpty_(Stack *);#endif

stack.c

/*************************************************************************> File Name: Stack/stack.c> Author: bairutai> Mail: bairutai@aliyun.com > Created Time: 2015年09月11日 星期五 11时07分12秒 ************************************************************************/#include<stdio.h>#include"stack.h"#include<malloc.h>Stack *InitEmptyStack(){Stack *stack = (Stack*)malloc(sizeof(Stack));stack->size = 0;stack->head = NULL;}void destory(Stack *stack){if (NULL == stack) {return;}while(!isEmpty_(stack)){pop(stack);}free(stack);}bool isEmpty_(Stack *stack){if (NULL == stack) {return false;}else{if(0 == stack->size && NULL == stack->head){return true;}else{return false;}}}void push(Stack *stack, L data){if (NULL == stack){return;}else {if (isEmpty_(stack)){PNode node = (PNode)malloc(sizeof(Node_));node->data = data;node->next = NULL;stack->head = node;stack->size++;}else{PNode node = (PNode)malloc(sizeof(Node_));node->data = data;node->next = stack->head;stack->head = node;stack->size++;}}}PNode pop(Stack *stack){if(NULL == stack){return NULL;}else{if(isEmpty_(stack)){return NULL;}else{PNode node = stack->head;stack->head = node->next;stack->size--;return node;}}}

test.c

/*************************************************************************> File Name: test.c> Author: bairutai> Mail: bairutai@aliyun.com > Created Time: 2015年09月22日 星期二 16时11分26秒 ************************************************************************/#include<stdio.h>#include"BiTree.h"main(){Node* n1 = MakeNode(10,NULL,NULL);Node* n2 = MakeNode(20,NULL,NULL);Node* n3 = MakeNode(30,n1,n2);Node* n4 = MakeNode(40,NULL,NULL);Node* n5 = MakeNode(50,NULL,NULL);Node* n6 = MakeNode(60,n4,n5);Node* root = MakeNode(70,n3,n6);BiTree *biTree = initBiTree(&root);printf("the depth is %d \n", getDepth(*biTree));printf("前序遍历:");pre_order(root);printf("\n");printf("中序遍历:");mid_order(root);printf("\n");printf("后序遍历:");after_order(root);printf("\n");printf("非递归前序遍历:");pre_order_(root);printf("\n");printf("非递归中序遍历:");mid_order_(root);printf("\n");printf("非递归后序遍历:");after_order_(root);printf("\n");DestoryBiTree(biTree);if(isEmpty(*biTree)){printf("二叉树为空\n");}else{printf("the address of biTree is %p\n", biTree);}}

结果

the depth is 3 前序遍历:70 30 10 20 60 40 50 中序遍历:10 30 20 70 40 60 50 后序遍历:10 20 30 40 50 60 70 非递归前序遍历:70 30 10 20 60 40 50 非递归中序遍历:10 30 20 70 40 60 50 非递归后序遍历:10 20 30 40 50 60 70 destory  10 destory  20 destory  30 destory  40 destory  50 destory  60 destory  70 二叉树为空



0 0
原创粉丝点击