函数原型
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);
}