C语言:二叉树的相关操作

/*
	二叉树的例子:二叉链建立表结构
	1.二叉树的遍历建立
	2.二叉树的三种递归遍历
	3.非递归(栈结构)的中序遍历
	4.层序遍历(队列)
*/

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

//二叉树节点
typedef struct Node
{
	int data;   //数据域  
	struct Node * Lchild;   //指向左孩子
	struct Node * Rchild;   //指向右孩子
}BiNode, * BiTree;

//定义栈,用非递归的方法中序遍历二叉树
typedef struct stack
{
	int top;  //指向栈顶,有效元素的上一个位置
	BiTree * ele;  //栈存储空间的基址,存储二叉树节点
}Stack;

//以树节点为元素的链表节点
typedef struct node
{
	BiTree data;
	struct node * pNext;
}NODE, * PNODE;

//定义队列,层序遍历
typedef struct queue
{
	PNODE front;  //对首
	PNODE rear;  //队尾	
}Queue;


void inital(BiTree &T);
void creat(BiTree &T);
int BiTreeDepth(BiTree T);
void InOrderTraverse(BiTree T);
void PreOrderTraverse(BiTree T);
void PostOrderTraverse(BiTree T);

void inOrder(BiTree T);
void initalStack(Stack &s);
void push(Stack &S, BiTree t);
void pop(Stack &S, BiTree &t);
bool empty_stack(Stack S);
bool getTop(Stack S, BiTree &p);
void visit(BiTree p);

void levelTraverse(BiTree T);
void initalQueue(Queue &Q);
void inQueue(Queue &Q, BiTree T);
void outQueue(Queue &Q, PNODE &p);
bool empty_queue(Queue Q);
void visit_pnode(PNODE p);

int main(void)
{
	BiTree T;
	inital(T);  //二叉树初始化

	//创建二叉树
	creat(T);  

	//求二叉树的深度
	int deep = BiTreeDepth(T);
	printf("树T的深度为:%d\n", deep);

	//中序遍历二叉树
	printf("中序遍历:");
	InOrderTraverse(T);
	printf("\n");

	printf("前序遍历:");
	PreOrderTraverse(T);
	printf("\n");

	printf("后序遍历:");
	PostOrderTraverse(T);
	printf("\n");

	printf("非递归中序遍历:");
	inOrder(T);
	printf("\n");

	printf("层序遍历:");
	levelTraverse(T);
	printf("\n");

	return 0;
}

//初始化树
void inital(BiTree &T)
{
	T = NULL;  //根节点为NULL
}

//创建二叉树
/*递归的按先序的方法创建二叉树*/
void creat(BiTree &T)
{
	int ch;
	printf("输入节点的值,0代表空值:"); 
	scanf("%d", &ch);    //输入一个整数值,回车

	if(ch == 0)    //值为0时,不创建节点
		T = NULL;
	else            //值不为0时,创建新节点
	{
		T = (BiTree)malloc(sizeof(BiNode));
		if(T == NULL)
			exit(0);

		T->data = ch;
		creat(T->Lchild);
		creat(T->Rchild);
	}
	
	return;
}

//求二叉树的深度
int BiTreeDepth(BiTree T)
{
	int i, j;

	if(T == NULL)   //程序的出口
		return 0;
	else
	{
		if(T->Lchild)   //左孩子深度
		{
			i = BiTreeDepth(T->Lchild);
		}
		else   //为空时,深度为0
		{
			i = 0;
		}

		if(T->Rchild)   //右孩子深度
		{
			j = BiTreeDepth(T->Rchild);
		}
		else
		{
			j = 0;
		}

		return (i >= j) ? (i+1):(j+1);   //去左右孩子的最大深度
	}
}

//中序遍历,左子树,根节点,右子树
void InOrderTraverse(BiTree T)
{
	if(T == NULL)
		return;
	else
	{
		InOrderTraverse(T->Lchild);  
		printf("%d ", T->data);
		InOrderTraverse(T->Rchild);
	}
}

//前序遍历,根节点,左子树,右子树
void PreOrderTraverse(BiTree T)
{
	if(T == NULL)
		return;
	else
	{
		printf("%d ", T->data);
		PreOrderTraverse(T->Lchild);
		PreOrderTraverse(T->Rchild);
	}
}

//后续遍历,左子树,右子树,根节点
void PostOrderTraverse(BiTree T)
{
	if(T == NULL)
		return; 
	else
	{
		PostOrderTraverse(T->Lchild);
		PostOrderTraverse(T->Rchild);
		printf("%d ", T->data);
	}
}

//非递归的中序遍历二叉树
/*
	1.所有左孩子入栈
	2.栈顶元素出栈,并访问
	3.栈顶元素的右孩子入栈
*/
void inOrder(BiTree T)
{
	Stack S;   //建立栈
	initalStack(S);  //初始化栈

	BiTree p = NULL;

	//根指针进栈
	push(S, T);

	while(!empty_stack(S))
	{
		//获取栈顶元素,	其左孩子入栈  		
		while( getTop(S, p) && p != NULL )
		{
			push(S, p->Lchild);
		}

		//最后一个空元素出栈
		pop(S, p);

		if(!empty_stack(S))
		{
			//栈顶左孩子出栈
			pop(S, p);

			//访问该节点
			visit(p);

			//右孩子入栈顶 
			push(S, p->Rchild);
		}
	}
}

//层序遍历
/*
	1.利用队列
	2.首节点入队列,在出队列,左右孩子入队列
	3.左孩子出队列,其左右孩子在入队列。。。
*/

void levelTraverse(BiTree T)
{
	//建立队列
	Queue Q;
	PNODE p;
	
	//初始化队列
	initalQueue(Q);

	//根节点入队列
	inQueue(Q, T);

	while(!empty_queue(Q))  //队列不为空时
	{
		//对首元素出队列
		outQueue(Q, p);

		visit_pnode(p);   //访问p节点

		//对首元素的的左右节点入队列
		if(p->data->Lchild != NULL)
			inQueue(Q, p->data->Lchild);
		if(p->data->Rchild != NULL)
			inQueue(Q, p->data->Rchild);
	}


}

//初始化栈
void initalStack(Stack &s)
{
	s.top = 0;
	s.ele = (BiTree*)malloc(sizeof(BiTree) * 10);
}

//二叉树的节点入栈
void push(Stack &S, BiTree t)
{
	S.ele[S.top] = t;
	S.top ++;
}

//二叉树的节点出栈
void pop(Stack &S, BiTree &t)
{
	S.top --;
	t = S.ele[S.top];
}

//栈是否空
bool empty_stack(Stack S)
{
	if(S.top == 0)
		return true;
	else
		return false;
}

//获取栈顶元素,保存在p
bool getTop(Stack S, BiTree &p)
{
	if(!empty_stack(S))  //栈为非空时
		p = S.ele[S.top-1];
	else
		p = NULL;

	return true;
}

//访问数节点p
void visit(BiTree p)
{
	printf("%d ", p->data);
}

//初始化队列
void initalQueue(Queue &Q)
{
	Q.front = (PNODE)malloc(sizeof(NODE));  //创建头结点,头指针
	Q.front->pNext = NULL;    
	Q.rear = Q.front;   //尾指针
}

//节点T入队列Q
void inQueue(Queue &Q, BiTree T)
{
	PNODE pNew = (PNODE)malloc(sizeof(NODE));  //建立新节点
	pNew->data = T;
	pNew->pNext = NULL;

	Q.rear->pNext = pNew;  //新节点挂在尾节点后面
	Q.rear = pNew;

}

//判断队列是否为空
bool empty_queue(Queue Q)
{
	if(Q.front->pNext == NULL)
		return true;
	else
		return false;
}

//元素出队列
void outQueue(Queue &Q, PNODE &p)
{
 	p = Q.front->pNext;
	Q.front ->pNext = p->pNext;

	if(p == Q.rear)  //当最后一个元素出队后,重新把尾节点和头结点连在一起
		Q.front = Q.rear;

}

//访问链表节点p
void visit_pnode(PNODE p)
{
	printf("%d ", p->data->data);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本课程主要以口袋西游为例,学习一个网络游戏是怎么通过游戏服务器与玩家客户端进行通信交互的,通过OD,CE等工具对游戏进行调试,找到各个数据基址(例如角色基址,背包基址等),找出游戏里面的功能CALL(例如寻路CALL,打坐CALL等)及参数分析,并且编码实现功能。本课程可以带领你游戏逆向入门可以学会 CE,OD,找游戏基址,功能CALL等实现变态功能可以更深入的理解从高级语言到汇编语言的一个对应过程可以学会 逆向软件  外挂与反外挂 破解防破解  游戏安全的基础知识可以为以后的及逆向高级课程 打下良好的基础可以自己分析游戏数据,用C语言实现游戏外挂功能等重点:  本套课程的重点就是带领大家分析游戏数据,毫不客气的说,各位学完此套课程对分析游戏数据这块会有一个质的飞跃。课程目录  01.课程简介及功能演示  02.CE找人物基址及人物属性偏移  03.OD找人物基址及人物属性偏移  04.创建MFC DLL项目  05.代码实现输出人物信息  06.发包函数概述  07.怎么看待重写的发包函数  08.普通发包与线程发包  09.找打坐CALL及参数分析  10.代码实现打坐CALL  11.喊话CALL及参数分析  12.代码实现喊话CALL  13.找寻路CALL及参数分析  14.代码编写寻路CALL  15.穿装备CALL及参数分析  16.代码实现穿装备CALL  17.NPC对话CALL  18.代码实现NPC对话CALL  19.唤出宠物  20.宠物合体  21.收回宠物  22.取下宠物
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值