C | 二叉树的创建销毁遍历,计算叶子数,深度以及对二叉树进行拷贝等基本操作

27 篇文章 1 订阅
13 篇文章 0 订阅
  • 二叉树是一块比较重要的知识点,而且是从线性结构到树形结构的一个跨越,建议大家动手实现以下。
  • 树是递归算法最好的应用,当然不嫌麻烦的话也可以用栈。

前序遍历初始化树:

void InitializeTree(Tree *T) {
	char ch;
	scanf("%c",&ch);
	if (ch == '*') {
		(*T) = NULL;
	}
	else {
		if (!((*T) = (Node*)malloc(sizeof(Node))))
			exit(-1);
		(*T)->data = ch;
		InitializeTree(&((*T)->lchild));
		InitializeTree(&((*T)->rchild));	
	}

}

后序遍历销毁二叉树

void DestroyTree(Tree *T) {
	if ((*T)) {
		DestroyTree(&((*T)->lchild));
		DestroyTree(&((*T)->rchild));
		free((*T));
		(*T) = NULL;
	}	
}

前序遍历打印二叉树

void PreOrderTraverse(Tree T, void (*Visit)(ElemType e)) {
	if (T) {
		Visit(T->data);
		PreOrderTraverse(T->lchild,Visit);
		PreOrderTraverse(T->rchild,Visit);
	}
}

中序遍历打印二叉树

void InOrderTraverse(Tree T, void (*Visit)(ElemType e)) {
	if(T) {
		InOrderTraverse(T->lchild,Visit);
		Visit(T->data);
		InOrderTraverse(T->rchild,Visit);
	}	
}

后序遍历打印二叉树

void PostOrderTraverse(Tree T, void (*Visit)(ElemType e)) {
	if (T) {
		PostOrderTraverse(T->lchild,Visit);
		PostOrderTraverse(T->rchild,Visit);
		Visit(T->data);	
	}
}

前序遍历计算叶子结点数

void CountLeaf1(Tree T, int *count) {
	if (T) {
		if (!(T->lchild) && !(T->rchild)) {
			(*count)++;	
		}
		CountLeaf1(T->lchild,count);
		CountLeaf1(T->rchild,count);	
	}
	else 
		(*count) = 0;
}

计算叶子结点的简化方法:

unsigned int CountLeaf2(Tree T) {
	if (!T) {
		return 0;
	}
	else if (!T->lchild && !T->rchild)
		return 1;
	else
		return CountLeaf2(T->lchild)+CountLeaf2(T->rchild);
}

后序遍历计算二叉树深度

unsigned int DepthOfTree(Tree T) {	
	if (T) {
		return DepthOfTree(T->lchild) > DepthOfTree(T->rchild) ? DepthOfTree(T->lchild) + 1 : DepthOfTree(T->rchild) + 1;
	}
	return 0;
}

后序遍历复制二叉树

Tree CopyTree(Tree T) {
	if (T) {
		Tree ltree = NULL;
		Tree rtree = NULL;
		if (T->lchild)
			ltree = CopyTree(T->lchild);
		if (T->rchild)
			rtree = CopyTree(T->rchild);
		Tree New = (Node*)malloc(sizeof(Node));
		New->data = T->data;
		New->lchild = ltree;
		New->rchild = rtree;
		return New;
	}
	return NULL;	
}
  • 是不是惊喜的发现所有的算法都是用递归来实现
  • 递归在二叉树和树种应用真的很广,大家又不太理解的建议找个二叉树的基本图手动模拟算法去遍历尝试一下,好记性不如烂笔头

最后附上源码:

Tree.h

#ifndef _TREE_H_
#define _TREE_H_
#include <stdbool.h>

typedef char ElemType;

typedef struct BiTNode {
	ElemType data;
	struct BiTNode *lchild, *rchild;
} Node, *Tree;

//Initialize a tree
void InitializeTree(Tree *T);

//Destroy a tree
void DestroyTree(Tree *T);

//void PreOrderTraverse(Tree T);

//Pre-Order traversing a tree
void PreOrderTraverse(Tree T, void (*Visit)(ElemType e));

//In-Order traversing a tree
void InOrderTraverse(Tree T, void (*Visit)(ElemType e));

//using in c++
void InOrderTraverse2(Tree T, void (*Visit)(ElemType e));

//Post-Order traversing a tree
void PostOrderTraverse(Tree T, void (*Visit)(ElemType e));

//Level-Order traversing a tree
void LevelOrderTraverse(Tree T, void (*Visit)(ElemType e));

//Count the number of leaf nodes in the binary tree
void CountLeaf1(Tree T,  int *count);

//Another way to count the number of leaf nodes in the binary tree
unsigned int CountLeaf2(Tree T);

//Calculate the depth of the binary tree
unsigned int DepthOfTree(Tree T);

//Copy the binary tree
Tree CopyTree(Tree T);
#endif

Tree.c

#include <stdio.h>
#include "Tree.h"
#include <stdlib.h>
#include <string.h>
#include "../stack/Stack.h"

void InitializeTree(Tree *T) {
	char ch;
	scanf("%c",&ch);
	if (ch == '*') {
		(*T) = NULL;
	}
	else {
		if (!((*T) = (Node*)malloc(sizeof(Node))))
			exit(-1);
		(*T)->data = ch;
		InitializeTree(&((*T)->lchild));
		InitializeTree(&((*T)->rchild));	
	}

}

void DestroyTree(Tree *T) {
	if ((*T)) {
		DestroyTree(&((*T)->lchild));
		DestroyTree(&((*T)->rchild));
		//(*T)->data='*';
		free((*T));
		(*T) = NULL;
	}	
}

void PreOrderTraverse(Tree T, void (*Visit)(ElemType e)) {
	if (T) {
		Visit(T->data);
		PreOrderTraverse(T->lchild,Visit);
		PreOrderTraverse(T->rchild,Visit);
	}
}

void InOrderTraverse(Tree T, void (*Visit)(ElemType e)) {
	if(T) {
		InOrderTraverse(T->lchild,Visit);
		Visit(T->data);
		InOrderTraverse(T->rchild,Visit);
	}	
}

void PostOrderTraverse(Tree T, void (*Visit)(ElemType e)) {
	if (T) {
		PostOrderTraverse(T->lchild,Visit);
		PostOrderTraverse(T->rchild,Visit);
		Visit(T->data);	
	}
}
//I'm too lazy to want to call stack interface,so this function need to realise using c++
/*void InOrderTraverse2(Tree T, void (*Visit)(ElemType e)) {
	stack<Tree> S;
	Tree p;
	p = T;
	S.push(p);
	while (p->lchild != NULL) {
		p = p->lchild;
		S.push(p);
	}
		while (!S.empty()) {
			p = S.top();
			Visit(p->data);
			S.pop();
			if (p->rchild != NULL) {
				p=p->rchild;
				S.push(p);
				while (p->lchild != NULL) {
					p = p->lchild;
					S.push(p);
				}			
			}
		}
}
*/
void CountLeaf1(Tree T, int *count) {
	if (T) {
		if (!(T->lchild) && !(T->rchild)) {
			(*count)++;	
		}
		CountLeaf1(T->lchild,count);
		CountLeaf1(T->rchild,count);	
	}
	else 
		(*count) = 0;
}

unsigned int CountLeaf2(Tree T) {
	if (!T) {
		return 0;
	}
	else if (!T->lchild && !T->rchild)
		return 1;
	else
		return CountLeaf2(T->lchild)+CountLeaf2(T->rchild);
}

unsigned int DepthOfTree(Tree T) {	
	if (T) {
		return DepthOfTree(T->lchild) > DepthOfTree(T->rchild) ? DepthOfTree(T->lchild) + 1 : DepthOfTree(T->rchild) + 1;
	}
	return 0;
}

Tree CopyTree(Tree T) {
	if (T) {
		Tree ltree = NULL;
		Tree rtree = NULL;
		if (T->lchild)
			ltree = CopyTree(T->lchild);
		if (T->rchild)
			rtree = CopyTree(T->rchild);
		Tree New = (Node*)malloc(sizeof(Node));
		New->data = T->data;
		New->lchild = ltree;
		New->rchild = rtree;
		return New;
	}
	return NULL;	
}

main.c

#include "Tree.h"
#include <stdio.h>
void Visit(ElemType e);
void Visit(ElemType e) {
	printf("%c\n",e);
}
int main () {
	int count = 0;
	Tree T;
	InitializeTree(&T);
	/*CountLeaf1(T,&count);
	printf("%d\n",count);
	printf("%d\n",DepthOfTree(T));
	PreOrderTraverse(T,Visit);
	InOrderTraverse(T,Visit);
	PostOrderTraverse(T,Visit);*/
	Tree A = CopyTree(T);
	PreOrderTraverse(A,Visit);
	DestroyTree(&T);
	DestroyTree(&A);
	return 0;	
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值