数据结构-C语言实现一个二叉树

命名恐慌症,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: [email protected] 
	> 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: [email protected] 
  > 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: [email protected] 
	> 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: [email protected] 
	> 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: [email protected] 
	> 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 
二叉树为空

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章