#include<winuser.inl>
#include<stdio.h>
#include <time.h>
#include <cstdlib>
#include <string.h>
/*
3 5 8 2 6 9 7
前序遍历:3 5 2 6 8 9 7
中序遍历:2 6 5 3 9 8 7
后序遍历:2 6 5 9 7 8 3
树:
3(0)
5(1) 8(2)
2(3) 6(4) 9(5) 7(6)
*/
#define left 1
#define right 2
typedef struct tag_node
{
int data;
int index;
struct tag_node *pLeftChild, * pRightChild, * pParent;
}Node;
typedef struct tag_tree
{
//该结构体指向树的根节点
Node* root;
}Tree;
bool CreateTree(Tree** pTree, Node* pRoot);
void DestroyTree(Tree* pTree);
Node* SearchNodeindex(Node* pNode, int nodeIndex); //节点层面
Node* SearchNode(Tree* pTree, int nodeindex); //树层面
bool AddNode(Tree* pTree, int nodeindex, Node* pNode, int d1irection);
void DeleteN(Node* pNode, int direaction); //节点层面
bool DeleteNode(Tree* pTree, int nodeindex, Node* pNode);
void PreorderNode(Node* pNode);
void PreorderPrintTree(Tree* pTree);
void MidOrderNode(Node* pNode);
void MidOrderPrintTree(Tree* pTree);
void FinOrderNode(Node* pNode);
void FinOrderPrintTree(Tree* pTree);
bool CreateTree(Tree** pTree, Node* pRoot)
{
*pTree = (Tree*)malloc(sizeof(Tree));
if (*pTree == NULL)
{
printf("failed\n");
return false;
}
else
{
(*pTree)->root = (Node*)malloc(sizeof(Node));
if ((*pTree)->root == NULL)
{
printf("failed\n");
free(*pTree); //这里分配失败,就把前面的内存释放掉
return false;
}
//else 采用链表形式,不需要再左初始化
//{
// //给树的所有节点赋初值为0
// for (int i = 0; i < MAXSIZE; i++)
// {
// (*pTree)->root[i].data = 0;
// }
// //创建的数的第一个节点需要有数据,将传进来的数据复制给第一个节点
//
else
{
//(*pTree)->root[0] = *pRoot;
*((*pTree)->root) = *pRoot; //对象拷贝,与下面等价
//(*pTree)->root->data = pRoot->data;
//(*pTree)->root->index = pRoot->index;
//(*pTree)->root->pLeftChild = NULL;
//(*pTree)->root->pRightChild = NULL;
//(*pTree)->root->pParent = NULL;
return true;
}
}
}
void DeleteN(Node* pNode, int direaction)
{
//判断传入进来的指针是否为空
if (pNode != NULL)
{
DeleteN(pNode->pLeftChild, left);
DeleteN(pNode->pRightChild, right);
/*
删除某一结点的左右子节点之后,进一步删除自己,删除自己之前
需要将判断当前节点是属于自己父节点的左节点还是右节点,然后进一步
将父节点对一个的左节点(右节点)置为null,然后再释放当前节点的内存
*/
if (direaction == left)
{
pNode ->pParent ->pLeftChild = NULL;
}
if (direaction == right)
{
pNode->pParent ->pRightChild = NULL;
}
free(pNode);
pNode = NULL;
}
}
void DestroyTree(Tree* pTree)
{
//需要逐一销毁每一个节点
DeleteN(pTree->root->pLeftChild, left);
DeleteN(pTree->root->pRightChild, right);
free(pTree->root);
free(pTree);
}
//bool SearchNode(Tree* pTree, int nodeindex ,Node *node)
//{
// 这里的Node *node是用来存放要查找的那个数据
// if (nodeindex < 0 || nodeindex >= MAXSIZE)
// {
// return false;
// }
// else
// {
// if (pTree->root[nodeindex].data == 0)
// {
// return false;
// }
// else
// {
// node->data = pTree->root[nodeindex].data;
// return true;
// }
// }
//}
Node* SearchNodeindex(Node* pNode, int nodeIndex)
{
if (pNode == NULL)
{
return NULL;
}
else
{
/*
递归查找和传入索引一致的节点
判断当前节点是否满足条件,不满足,则进一步查找当前节点的左子树,返回左子树
的节点,以便递归进而寻炸左子树的左子树
如果左子树是空的,那么只能进一步递归查找右子树
*/
if (pNode->index == nodeIndex)
{
return pNode;
}
else
{
Node* temp = NULL;
temp = SearchNodeindex(pNode->pLeftChild, nodeIndex);
if (temp != NULL)
{
return temp;
}
else
{
temp = SearchNodeindex(pNode->pRightChild, nodeIndex);
return temp;
}
}
}
}
Node* SearchNode(Tree* pTree, int nodeindex)
{
return SearchNodeindex(pTree->root, nodeindex);
}
bool AddNode(Tree* pTree, int nodeindex, Node* pNode, int d1irection)
{
/*
1.找到要添加元素的节点
2.判断该节点是否为空,为空,不能添加孩子,如果不为空,判断是要添加左孩子还是右
,然后需要进一步判断(左)右孩子是否为空,为空才能添加子孩子
*/
Node* temp;
Node* newNode = NULL;
temp = SearchNode(pTree, nodeindex);
//开辟一个节点的空间来存放传进来的 pNode节点数据,如果直接将temp指向pNode,
//pNode申请的内存空间是在函数外面申请的,如果函数外面释放掉pNode的空间,那么Temp
//就不知道指向哪了,所以最好的方式是在函数里面自己申请一个空间来存放节点数据
if (temp != NULL)
{
if (d1irection == left)
{
if (temp->pLeftChild == NULL)
{
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL)
{
return false;
}
else
{
*newNode = *pNode; //数据拷贝
temp->pLeftChild = newNode; //将temp的左孩子指向newnode
//另外,每一个节点里面处理孩子节点,还有父亲节点
newNode->pParent = temp; //将新节点的父节点指向temp
return true;
}
}
else
{
return false;
}
}
if (d1irection == right)
{
if (temp->pRightChild == NULL)
{
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL)
{
return false;
}
else
{
*newNode = *pNode; //数据拷贝
temp->pRightChild = newNode; //将temp的左孩子指向newnode
//另外,每一个节点里面处理孩子节点,还有父亲节点
newNode->pParent = temp; //将新节点的父节点指向temp
return true;
}
}
else
{
return false;
}
}
}
else
{
return false;
}
}
bool DeleteNode(Tree* pTree, int nodeindex, Node* pNode)
{
//DeleteNode这里是删除指定的节点,同时要删除指定节点之后的所有子节点
//DeleteN作用是删除传入节点以下的全部节点,起始两个函数作用是一样的
//需要先找到要删除的节点
Node* temp;
temp = SearchNode(pTree,nodeindex);
if (temp != NULL)
{
//递归删除掉索引到的节点的全部子节点
DeleteN(temp ->pLeftChild, left);
DeleteN(temp ->pRightChild, right);
//下面和在DeleteN里面一样,需要将当前的节点置为null,需要找到当前
//节点的父节点,判断当前节点是父节点的左孩子还是右孩子
if (temp->pParent->pLeftChild == temp)
{
temp->pParent->pLeftChild = NULL;
}
if (temp->pParent->pRightChild == temp)
{
temp->pParent->pRightChild = NULL;
}
free(temp);
temp = NULL;
return true;
}
else
{
return false;
}
}
void PreorderNode(Node* pNode)
{
if (pNode != NULL)
{
printf("%d ", pNode->data);
PreorderNode(pNode->pLeftChild);
PreorderNode(pNode->pRightChild);
}
}
void PreorderPrintTree(Tree* pTree)
{
//根左右
printf("the tree is:\n");
PreorderNode(pTree->root);
printf("\n");
}
void MidOrderNode(Node* pNode)
{
if (pNode != NULL)
{
MidOrderNode(pNode->pLeftChild);
printf("%d ", pNode->data);
MidOrderNode(pNode->pRightChild);
}
}
void MidOrderPrintTree(Tree* pTree)
{
//左中右
printf("the tree is:\n");
MidOrderNode(pTree->root);
printf("\n");
}
void FinOrderNode(Node* pNode)
{
if (pNode != NULL)
{
FinOrderNode(pNode->pLeftChild);
FinOrderNode(pNode->pRightChild);
printf("%d ", pNode->data);
}
}
void FinOrderPrintTree(Tree* pTree)
{
//左右根
printf("the tree is:\n");
FinOrderNode(pTree->root);
printf("\n");
}
int main()
{
Tree* pTree = NULL;
Node node = { 3 ,0, NULL, NULL ,NULL }; //给一个初值
Node node1 = { 5 ,1, NULL, NULL ,NULL };
Node node2 = { 8 ,2, NULL, NULL ,NULL };
Node node3 = { 2 ,3, NULL, NULL ,NULL };
Node node4 = { 6 ,4, NULL, NULL ,NULL };
Node node5 = { 9 ,5, NULL, NULL ,NULL };
Node node6 = { 7 ,6, NULL, NULL ,NULL };
Node *node_d;
CreateTree(&pTree, &node);
AddNode(pTree, 0, &node1, left);
AddNode(pTree, 0, &node2, right);
AddNode(pTree, 1, &node3, left);
AddNode(pTree, 1, &node4, right);
AddNode(pTree, 2, &node5, left);
AddNode(pTree, 2, &node6, right);
PreorderPrintTree(pTree);
//node_d = SearchNode(pTree, 3);
//printf("index is %d ,data is %d\n", 3, node_d->data);
printf("after delete node,");
node_d = (Node*)malloc(sizeof(Node));
DeleteNode(pTree, 2, node_d);
PreorderPrintTree(pTree);
DestroyTree(pTree);
return 0;
}
链表实现二叉树
最新推荐文章于 2023-05-31 16:27:38 发布