數據結構-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 
二叉樹爲空

 

 

 

 

 

 

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