命名恐慌症,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
二叉樹爲空