【C】【Tree】二叉排序树的实现

函数原型

bool InitTree(Tree* ptree); //初始化树
bool TreeIsEmpty(Tree* ptree); //判断树是否为空
bool TreeIsFull(Tree* ptree); //判断树是否已满
int TreeNodeCount(Tree* ptree); //确定树的节点数

bool ToLeft(Item* root_item, Item* new_item);//判断新节点该加在左边还是右边
bool ToRight(Item* root_item, Item* new_item);
Pair SeekItem(Tree* ptree, Item* new_item);//查找项

bool AddItemToNode(Tree* ptree, Item* item); //添加项目给新节点
void AddNodeToTree(Node* root, Node* pnew); //添加节点给树(函数对子树操作),root是子树的根节点,不是树的

void ShowTree(Tree* pree);//显示树
void LDR(Node* root);//中序递归遍历
void DLR(Node* root);//先序递归遍历
void LRD(Node* root);//后序递归遍历

bool DelItemToNode(Tree* ptree, Item* item);
bool DelNodeToTree(Node** pnode); 
bool InTree(Tree* ptree, Item* item); //查找节点

源代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct something{
	int a;
} Item;

typedef struct node {
	Item item;
	struct node* left; //指向左节点的指针
	struct node* right; //指向右节点的指针
}Node;

typedef struct tree{
	Node* root; //指向树根的指针
	int size; //树的节点
}Tree;

typedef struct pair {
	Node* parent;
	Node* child;
}Pair;

bool InitTree(Tree* ptree); //初始化树
bool TreeIsEmpty(Tree* ptree); //判断树是否为空
bool TreeIsFull(Tree* ptree); //判断树是否已满
int TreeNodeCount(Tree* ptree); //确定树的节点数

bool ToLeft(Item* root_item, Item* new_item);//判断新节点该加在左边还是右边
bool ToRight(Item* root_item, Item* new_item);
Pair SeekItem(Tree* ptree, Item* new_item);//查找项

bool AddItemToNode(Tree* ptree, Item* item); //添加项目给新节点
void AddNodeToTree(Node* root, Node* pnew); //添加节点给树(函数对子树操作),root是子树的根节点,不是树的

void ShowTree(Tree* pree);//显示树
void LDR(Node* root);//中序递归遍历
void DLR(Node* root);//先序递归遍历
void LRD(Node* root);//后序递归遍历

bool DelItemToNode(Tree* ptree, Item* item);
bool DelNodeToTree(Node** pnode); 
bool InTree(Tree* ptree, Item* item); //查找节点

bool InitTree(Tree* ptree)
{
	ptree->size = 0;
	ptree->root = (Node*)malloc(sizeof(Node));	
	if (ptree->root == NULL)
		return false;

	ptree->root->left = NULL;
	ptree->root->right = NULL;

	return true;
}

bool TreeIsEmpty(Tree* ptree)
{
	if (0 == ptree->size)
		return true;
	return false;
}

bool TreeIsFull(Tree* ptree)
{
	Node* ptemp;
	ptemp = (Node*)malloc(sizeof(Node));
	if (ptemp == NULL)
		return true;
	free(ptemp);
	return false;
}

int TreeNodeCount(Tree* ptree)
{
	return ptree->size;
}

bool ToLeft(Item* root_item, Item* new_item)
{
	if (new_item->a < root_item->a)
		return true;
	return false;
}

bool ToRight(Item* root_item, Item* new_item)
{
	if (new_item->a > root_item->a)
		return true;
	return false;
}

Pair SeekItem(Tree* ptree, Item* new_item)
{
	//创建并初始化一个look结构体
	Pair look;
	look.parent = ptree->root;
	look.child = ptree->root;

	//树为空
	if (TreeIsEmpty(ptree) == true)
	{
		look.parent = NULL;
		look.child = NULL; 
		return look;
	}

	while (look.child != NULL)
	{
		if (ToLeft(&look.child->item, new_item))
		{
			look.parent = look.child;
			look.child = look.child->left;
		}

		else if (ToRight(&look.child->item, new_item))
		{
			look.parent = look.child;
			look.child = look.child->right;
		}
		else
			break;
	} //最后look.child == NULL 或 ptree.root

	return look;
}

bool AddItemToNode(Tree* ptree, Item* new_item)
{
	if (TreeIsFull(ptree) == true)
	{
		printf("数已满!\n");
		return false;
	}

	Node* pnew;
	pnew = (Node*)malloc(sizeof(Node));
	if (pnew == NULL)
		return false;
	pnew->left = NULL;
	pnew->right = NULL;

	pnew->item = *new_item; //项目导入节点

	if (SeekItem(ptree, new_item).child != NULL)
	{
		printf("项目相同!重新输入!\n");
		return false;
	}

	//如果树为空
	if (TreeIsEmpty(ptree) == true)
		ptree->root = pnew; //pnew作为根节点
	//如果非空
	else if (TreeIsEmpty(ptree) == false)
		AddNodeToTree(ptree->root, pnew);

	ptree->size++; //树节点数增加

	return true;
}

void AddNodeToTree(Node* root, Node* pnew)
{
	//如果小于根节点,准备放在左节点
	if (ToLeft(&root->item, &pnew->item) == true)
	{
		//如果子树为空(左节点为NULL),子树的左节点为新节点
		if (root->left == NULL)
			root->left = pnew;
		//如果子树非空,递归调用到下一级子树,对新子树进行操作
		else
			AddNodeToTree(root->left, pnew);
	}

	//如果大于根节点,放在右节点
	else if (ToRight(&root->item, &pnew->item) == true)
	{
		//如果子树右节点为空,右节点为新节点
		if (root->right == NULL)
			root->right = pnew;
		else
			AddNodeToTree(root->right, pnew);
	}
	else
	{
		printf("意外添加节点失败!\n");
		exit(1);
	}
}

void ShowTree(Tree* ptree)
{
	if (TreeIsEmpty(ptree) == true)
	{
		printf("树为空!\n");
		exit(1);
	}

	LDR(ptree->root);
	putchar('\n');
	DLR(ptree->root);
	putchar('\n');
	LRD(ptree->root);
}

void LDR(Node* root)
{
	if (root->left != NULL)
		LDR(root->left);//一直递归到底层最左边节点

	//第一个打印的就是底层最左节点,然后回到上一层,打印上一层的最左节点。
	//此时上一层最左节点正好是下一层的根节点,符合中序遍历的左中
	printf("%d ", root->item.a);							

	//打印完左中后,开始考虑右,对右子树重复进行上面的操作
	if (root->right != NULL)
		LDR(root->right);
}

void DLR(Node* root)
{
	printf("%d ", root->item.a);

	if (root->left != NULL)
		DLR(root->left);

	if (root->right != NULL)
		DLR(root->right);
}

void LRD(Node* root)
{
	if (root->left != NULL)
		LRD(root->left);

	if (root->right != NULL)
		LRD(root->right);

	printf("%d ", root->item.a);
}

bool DelItemToNode(Tree* ptree, Item* item)
{
	Pair look;
	look = SeekItem(ptree, item);
	if (look.child == NULL)
	{
		printf("未查找到此项!\n");
		return false;
	}
	//删除根节点
	if (look.parent == look.child)
		DelNodeToTree(&ptree->root);
	//删除左节点
	else if (look.parent->left == look.child)
		DelNodeToTree(&look.parent->left);
	//删除右节点
	else if (look.parent->right == look.child)
		DelNodeToTree(&look.parent->right);
	else
		return false;

	printf("删除成功!\n");
	ptree->size--;

	return true;
}

bool DelNodeToTree(Node** pnode)
{
	Node* ptemp;

	//pnode左子树为空
	if ((*pnode)->left == NULL)
	{
		ptemp = *pnode;
		*pnode = (*pnode)->right;
		free(ptemp);
	}
	//pnode右子树为空
	else if ((*pnode)->right == NULL)
	{
		ptemp = *pnode;
		*pnode = (*pnode)->left;
		free(ptemp);
	}
	//pnode有左右节点
	else
	{
		//一直搜寻到pnode的左子树的右子树的右节点为空的地方,将pnode的右子树接在此处
		for (ptemp = (*pnode)->left; ptemp->right != NULL; ptemp = ptemp->right)
			continue;
		ptemp->right = (*pnode)->right;

		ptemp = *pnode;
		*pnode = (*pnode)->left;
		free(ptemp);
	}
}

bool InTree(Tree* ptree, Item* item)
{
	return (SeekItem(ptree, item).child == NULL) ? false : true;
}

int main(void)
{
	Tree T;
	Item temp_item = {0};

	if (InitTree(&T) == true)
		printf("程序运行……\n");
	else
		exit(1);

	printf("开始添加节点!\n");
	while (scanf("%d", &temp_item.a) != 0)
	{
		while (getchar() != '\n')
			continue;
		AddItemToNode(&T, &temp_item);
	}
	ShowTree(&T);

	putchar('\n');
	while (getchar() != '\n')
		continue;

	printf("开始删除节点!\n");
	while (scanf("%d", &temp_item.a) != 0)
	{
		while (getchar() != '\n')
			continue;
		DelItemToNode(&T, &temp_item);
		ShowTree(&T);
		putchar('\n');
	}
	

	return 0;
 }

递归遍历

如果不能理解,就背下来
先L后R
将printf作为D
先序遍历D在LR前面
中序遍历D在LR中间
后序遍历D在LR后面


先序递归遍历

void DLR(Node* root)
{
	printf("%d ", root->item.a);

	if (root->left != NULL)
		DLR(root->left);

	if (root->right != NULL)
		DLR(root->right);
}

中序递归遍历

void LDR(Node* root)
{
	if (root->left != NULL)
		LDR(root->left);//一直递归到底层最左边节点

	//第一个打印的就是底层最左节点,然后回到上一层,打印上一层的最左节点。
	//此时上一层最左节点正好是下一层的根节点,符合中序遍历的左中
	printf("%d ", root->item.a);							

	//打印完左中后,开始考虑右,对右子树重复进行上面的操作
	if (root->right != NULL)
		LDR(root->right);
}

后序递归遍历

void LRD(Node* root)
{
	if (root->left != NULL)
		LRD(root->left);

	if (root->right != NULL)
		LRD(root->right);

	printf("%d ", root->item.a);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值