C语言二叉树代码实现

完全二叉树的概念:对一棵满二叉树,从下向上,从右向左,依次去掉若干个结点形成的二叉树称为完全二叉树。




btree.h  //二叉树头文件,用于声明数据类型和相关函数

#ifndef __BTREE_H__
#define __BTREE_H__

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef char dataype_bt;  //声明二叉树中存放的数据类型,便于后续更改

typedef struct btreenode{   //二叉树的节点结构:存放的数据 该节点的左子节点地址及右子节点地址。注意和单链表的区别,二叉树是非线性存储,单链表是线性存储
	dataype_bt data;
	struct btreenode *lchild,*rchild;
}btree_node,*btree_pnode;

extern btree_pnode create_btree1(void);    //通过递归方法创建一个二叉树
extern void create_btree(btree_pnode *T);  //通过递归方法创建一个二叉树(功能同上)
extern void pre_order(btree_pnode t);    //采用递归方法先序遍历
extern void unpre_order(btree_pnode t);  //采用非递归方法先序遍历
extern void mid_order(btree_pnode t);    //采用递归方法中序遍历
extern void post_order(btree_pnode t);   //采用递归方法后序遍历
extern void level_order(btree_pnode t);  //层次遍历
extern void travel(char const *str,void (*pfun)(btree_pnode),btree_pnode t);   //将上面的函数作为参数传入该函数(函数的回调),实现二叉树的创建 和 遍历,其中参数str可以是回调函数的功能描述
#endif

btree.c  //二叉树相关函数的实现方法

#include "btree.h"
#include "linkqueue.h"   //链式队列的头文件,关于链式队列的相关函数实现方法请查看博主相关链式队列的文章,这里不做细讲
#include "linkstack.h"   //链式栈的头文件,关于链式栈的相关函数实现方法请查看博主相关链式栈的文章,这里不做细讲

btree_pnode create_btree1(void)        //通过递归方法创建一个二叉树
{
	dataype_bt ch;
	btree_pnode new;
	scanf("%c",&ch);
	if('#'==ch)
	{
		return NULL;
	}
	else
	{
		//创建根结点
		new=(btree_pnode)malloc(sizeof(btree_node));
		if(NULL==new)
		{
			perror("malloc");
			exit(-1);
		}
		new->data=ch;
		//用相同方法创建左子数
		new->lchild=create_btree1();
		//用相同方法创建右子数
		new->rchild=create_btree1();
	}
	return new;
}

void create_btree(btree_pnode *T)          //通过递归方法创建一个二叉树(功能同上)
{
	dataype_bt ch;
	scanf("%c",&ch);
	if('#'==ch)
	{
		return ;
	}
	else{
		//创建根结点
		(*T)=(btree_pnode)malloc(sizeof(btree_node));
		if(NULL==(*T))
		{
			perror("malloc");
			exit(-1);
		}
		(*T)->data=ch;
		//用相同方法创建左子数
		create_btree(&((*T)->lchild));
		//用相同方法创建右子数
		create_btree(&((*T)->rchild));
	}
}

void pre_order(btree_pnode t)          //采用递归方法先序遍历
{
	if(t!=NULL)
	{
		//访问根结点
		printf("%c",t->data);
		//先序遍历左子树
		pre_order(t->lchild);
		//先序遍历右子树
		pre_order(t->rchild);
	}
}

void unpre_order(btree_pnode t)          //采用非递归方法先序遍历
{
	linklist top;//top为指向栈顶结点的指针

	top=stack_create();//初始化链式栈
	/*
		该函数包含的头文件 和 实现方法如下:
		#include "linkstack.h"   //链式栈的头文件,关于链式栈的相关函数实现方法请查看博主相关链式栈的文章,这里不做细讲
		linklist stack_create()
		{
			linklist s;

			if((s=(linklist)malloc(sizeof(listnode)))==NULL){
				puts("malloc failed");
				return NULL;
			}
			s->next=NULL;

			return s;
		}
	*/
	while(t!=NULL || !(stack_empty(top))){
		/*
			该函数包含的头文件 和 实现方法如下:
			#include "linkstack.h"   //链式栈的头文件,关于链式栈的相关函数实现方法请查看博主相关链式栈的文章,这里不做细讲
			int stack_empty(linklist s)  //判断栈是否为空(1表示空,0表示非空)
			{
				return (s->next==NULL ? 1:0);
			}
		*/
		if(t!=NULL){
			printf("%c",t->data);
			if(t->rchild !=NULL)
				stack_push(top,t->rchild);  //入栈
			/*
				该函数包含的头文件 和 实现方法如下:
				#include "linkstack.h"   //链式栈的头文件,关于链式栈的相关函数实现方法请查看博主相关链式栈的文章,这里不做细讲
				int stack_push(linklist s,datatype_ls value)  //入栈
				{
					linklist p;
					if((p=(linklist)malloc(sizeof(listnode)))==NULL)
					{
						puts("malloc failed");
						return -1;
					}

					p->data = value;
					p->next=s->next;
					s->next = p;

					return 0;
				}
			*/
			t=t->lchild;
		}else
			t=stack_pop(top);   //出栈
		/*
			该函数包含的头文件 和 实现方法如下:
			#include "linkstack.h"   //链式栈的头文件,关于链式栈的相关函数实现方法请查看博主相关链式栈的文章,这里不做细讲
			datatype_ls stack_pop(linklist s)    //出栈
			{
				linklist p;
				datatype_ls ret;

				p=s->next;
				s->next=p->next;
				ret=p->data;

				free(p);
				p=NULL;

				return ret;
			}
		*/
	}

	stack_free(top);   //释放栈
	/*
		该函数包含的头文件 和 实现方法如下:
		#include "linkstack.h"   //链式栈的头文件,关于链式栈的相关函数实现方法请查看博主相关链式栈的文章,这里不做细讲
		void stack_free(linklist s)    //释放栈
		{
			linklist p;

			printf("free:");
			p=s;
			while(p)
			{
				s=s->next;
				printf("%d ",p->data);
				free(p);
				p=s;
			}
			putchar(10);    //10 表示 回车符('\n')

		}
	*/
}

void mid_order(btree_pnode t)           //采用递归方法中序遍历
{
	if(t!=NULL)
	{
		//中序遍历左子树
		mid_order(t->lchild);
		//访问根结点
		printf("%c",t->data);
		//中序遍历右子树
		mid_order(t->rchild);
	}
}

void post_order(btree_pnode t)          //采用递归方法后序遍历
{
	if(t!=NULL)
	{
		//后序遍历左子树
		post_order(t->lchild);
		//后序遍历右子树
		post_order(t->rchild);
		//访问根结点
		printf("%c",t->data);
	}
}

void level_order(btree_pnode t)        //层次遍历
{
	link_pqueue q;
	init_linkqueue(&q);//初始化链式队列
	/*
		该函数包含的头文件 和 实现方法如下:
		#include "linkqueue.h"   //链式队列的头文件,关于链式队列的相关函数实现方法请查看博主相关链式队列的文章,这里不做细讲
		void init_linkqueue(link_pqueue *Q)     //创建队列
		{
			//申请front和rear的空间
			*Q=(link_pqueue)malloc(sizeof(link_queue));
			if((*Q)==NULL)
			{
				perror("malloc");
				exit(-1);
			}
			//申请头结点空间
			(*Q)->front=(linkqueue_pnode)malloc(sizeof(linkqueue_node));
			if((*Q)->front==NULL)
			{
				perror("malloc");
				exit(-1) ;
			}
 
			(*Q)->front->next=NULL;
			(*Q)->rear=(*Q)->front;
 
			return;
		}
	*/

	while(t!=NULL)
	{
		//访问t指向的结点数据
		printf("%c",t->data);
		//当t的左指针不为空,则入队
		if(t->lchild!=NULL)
			in_linkqueue(t->lchild,q);
		/*
			该函数包含的头文件 和 实现方法如下:
			#include "linkqueue.h"   //链式队列的头文件,关于链式队列的相关函数实现方法请查看博主相关链式队列的文章,这里不做细讲
			bool in_linkqueue(datatype data,link_pqueue q)   //入队
			{
				linkqueue_pnode  new;
 
				//申请数据结点空间
				new=(linkqueue_pnode)malloc(sizeof(linkqueue_node));
				if(new==NULL)
				{
					puts("入队失败!");
					return false;
				}
				//将数据存储在申请的空间
				new->data=data;
	
				//将new指向的结点插入到链式队列中
				new->next=q->rear->next;            //这里等价于new->next = NULL;
				q->rear->next=new;         
	
				//让rear指针指向新的队尾结点
				q->rear=q->rear->next;          //等价于q->rear = new;
 
				return true;
			}
		*/
		//当t的右指针不为空,则入队
		if(t->rchild!=NULL)
			in_linkqueue(t->rchild,q);
		//队列不为空,则出队
		if(!is_empty_linkqueue(q))
			out_linkqueue(q,&t);
		/*
			该函数包含的头文件 和 实现方法如下:
			#include "linkqueue.h"   //链式队列的头文件,关于链式队列的相关函数实现方法请查看博主相关链式队列的文章,这里不做细讲
			bool out_linkqueue(link_pqueue q,datatype *D)      //出队
			{
				linkqueue_pnode t;
				//判断队列是否空
				if(is_empty_linkqueue(q)){
					printf("队列已空!\n");
					return false;
				}
 
				//出队
				t=q->front;
				q->front =q->front->next;
				*D=q->front->data;
				free(t);
 
				return true;
			}
		*/
		else
			break;
	}
	free_linkqueue(q);           //释放队列
	/*
		该函数包含的头文件 和 实现方法如下:
		#include "linkqueue.h"   //链式队列的头文件,关于链式队列的相关函数实现方法请查看博主相关链式队列的文章,这里不做细讲
		void free_linkqueue(link_pqueue q)           //释放队列
		{
			link_pqueue p;
			p = q->front;
			while(p)
			{
				q->front = q->front->next;
				free(p);
				p = q->front;
			}
			free(q);
		}
	*/
}

void travel(char const *str,void (*pfun)(btree_pnode),btree_pnode t)      //将上面的函数作为参数传入该函数(函数的回调),实现二叉树的创建 和 遍历,其中参数str可以是回调函数的功能描述
{
	printf("%s",str);
	pfun(t);
	puts("");
}

猜你喜欢

转载自blog.csdn.net/weixin_39148042/article/details/80960356