浅谈二叉树的使用

2018/5/3

1.说在前面:由于数据结构已经学完了树,对于这种比较难的结构,说一点看法

2.二叉树:

1.由一个根节点和两个互不相较的子二叉树(左子树和右子树)组成的树

2.相关操作介绍:

1.创建结构体实现树的建立

对于树而言,依旧采取结构体指针的方式,树拥有着一个左子树,一个右子树和一个储存数据的位置

typedef struct Node
{
	int data;
	struct Node *leftchild;
	struct Node *rightchild;

}BitreeNode;

2.创建二叉树的头结点

先分配空间,再将左子树和右子树的位置全部变为空即可

void InitBitree(BitreeNode**root)
{
	*root = (BitreeNode*)malloc(sizeof(BitreeNode));//给结构体指针分配空间
	(*root)->leftchild = NULL;
	(*root)->rightchild = NULL;
}

3.在二叉树的左子树和右子树中插入结点

1.判断当前的树是否为空树

2.先保存当前结点的(左/右)子树,创建一个新的结点

3.将新创建的结点设置指向数值,然后插入设置结点和所保存子树之间(注意顺序:先和子树连接,再和当前结点连接)

4.返回所插入的值(注意函数设置的返回值:为结构体指针,方便返回插入结点)

//二叉树中左结点插入数据
//当前结点curr不为空,在curr结点的左子树中插入元素为x的新左子树
BitreeNode*InsertLeftNode(BitreeNode*curr, int x)
{
	BitreeNode *s,*t;
	//判断是否存在结点可以增加左右孩子结点
	if (curr == NULL)
	{
		return NULL;
	}
	t = curr->leftchild;//保存curr结点的左子树
	s = (BitreeNode*)malloc(sizeof(BitreeNode));//创建新的子树
	s->data = x;//该左子树的数据为x
	s->leftchild = t;//相当于在curr和t之间多加了一层s
	s->rightchild = NULL;
	curr->leftchild = s;
	return curr->leftchild;
}
//二叉树中右结点插入数据
//当前结点不为空,在curr结点的右子树中插入元素x的新右子树
BitreeNode*InsertRightNode(BitreeNode*curr, int x)
{
	BitreeNode *s, *t;//*s表示增加的指针,*t表示原指针
					  //判断是否存在结点可以增加左右孩子结点
	if (curr == NULL)
	{
		return NULL;
	}
	t = curr->rightchild;//保存curr结点的左子树
	s = (BitreeNode*)malloc(sizeof(BitreeNode));//创建新的子树
	s->data = x;//该左子树的数据为x
	s->rightchild = t;//相当于在curr和t之间多加了一层s
	s->leftchild = NULL;
	curr->rightchild = s;
	return curr->rightchild;
}

5.删除某个结点(左子树和右子树)

1.判断是否为空树

2.判断左子树和右子树是否为空,如果为空的话,直接返回NULL

不为空的话,将该结点的(左/右)结点进行删除

3.确定某个结点的左/右结点为空

4.返回结点

//如果curr非空,删除结点的左子树
BitreeNode *DeleteLeftTree(BitreeNode*curr)
{
	if (curr == NULL || curr->leftchild == NULL)
	{
		return NULL;
	}
	//Destroy(&curr->leftchild);
	curr->leftchild = NULL;
	return curr;
}
//如果curr成功,删除所指结点的右子树
BitreeNode *DeleteRightTree(BitreeNode*curr)
{
	if (curr == NULL || curr->rightchild == NULL)
	{
		return NULL;
	}
//	Destroy(&curr->rightchild);
	curr->rightchild = NULL;
	return curr;
}
//彻底删除(用于后序遍历)
/*void Destroy(BitreeNode **root)
{
	if ((*root) != NULL && (*root)->leftchild != NULL)
	{
		Destroy(&(*root)->leftchild);//遍历
	}
	if ((*root) != NULL && (*root)->rightchild != NULL)
	{
		Destroy(&(*root)->rightchild);//遍历
	}

	free(*root);
	//printf("删除成功\n");
}*/

5.遍历方法

采用了递归算法来实现(代码用前序遍历实现)
三种遍历方法的最终实现效果相同 
1.前序遍历:根 左 右
2.中序遍历:左 根 右
3.后序遍历:左 右 根

注意使用遍历的方法 函数中的变量之一为visit函数 

注意:采用的是递归的思路,函数的内部值之一为visit函数

void preOrder(BitreeNode*t, void Visit(int item))//对visit函数进行遍历树的值
{
	if (t != NULL)
	{
		Visit(t->data);//根
		preOrder(t->leftchild, Visit);//左
		preOrder(t->rightchild, Visit);//右
	}
}
void Visit(int item)
{
	printf("%c", item);
}

6.打印数

1.这是一种特殊的中序遍历方法(右 根 左)

2.注意格式问题(空格和横线的使用)

3.采用递归

4.先访问右结点,再访问中间结点,再访问左结点

void printTree(BitreeNode*t, int n)//n代表着遍历的层数
{
	
	//1.判断是否为空
	if (t == NULL)
		return;
	
	printTree(t->rightchild, n++);//访问右结点
	for (int i = 0; i < n; i++) printf("  ");//注意结构
	if (n >= 0)
	{
		//printf("--------");
		printf("%c\n", t->data);//实现根数据的显示
	}
	printTree(t->leftchild, n++);//访问左结点
}

7.查找数据

1.判断是否为空树

2.确定左结点有没有  如果有的话一直在左结点里找数

3.同样的方法在右结点里找

4.如果都没有 返回NULL;

BitreeNode* Search(BitreeNode*t, char x)
{
	BitreeNode *p;
	if (t->leftchild == NULL)
	{
		return NULL;//
	}
	if (t->leftchild != NULL)//说明该数字在左子树中出现
	{
		p = Search(t->leftchild, x);//在左子树中寻找
			if (p != NULL)//get it
			{
				
				return p;
			}
	}
	if (t->rightchild != NULL)
	{
		p = Search(t->rightchild, x);//在右子树中寻找
		if (p != NULL)//get it
		{
			
			return p;
		}
	}
	//如果既不在左指针也不在右指针中
	//return 0;//退出程序
}

8.测试程序

//实现二叉树的创建和简单使用
//创建二叉树结构体
//1.初始化二叉树
//2.创建根节点
//3.创建左右子树
//4.删除左右子树
//5.直接删除
#include<stdio.h>
#include<stdlib.h>
#include"Bitree.h"

void main()
{
	
	BitreeNode *root, *p, *pp;
	InitBitree(&root);//创建一个根节点
	p = InsertLeftNode(root, 'A');//创建第一个左结点
	p = InsertLeftNode(p, 'B');
	p = InsertLeftNode(p, 'D');
	p = InsertRightNode(p,'G');
	p = InsertRightNode(root->leftchild, 'C');
	pp = p;
	//创建最后的子结点
	InsertLeftNode(p, 'E');
	InsertRightNode(pp,'F');
	printTree(root->leftchild, 0);
	printf("\n进行前序遍历\n");
	preOrder(root->leftchild, Visit);
	Search(root, 'B');
	printf("\n");
	DeleteLeftTree(root->leftchild->leftchild);//删除根节点的左结点
	printTree(root->leftchild, 0);
	
	//Destroy(&root);//删除结点
	system("pause");
}













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值