版权声明:本博客为个人原创,转载请注明出处 https://blog.csdn.net/qq_33826564/article/details/81900744
目录
说明
- 用C语言实现数据结构,二叉排序树,可动态插入二叉树结点,遍历二叉树结点到一个链表。
代码
#include<stdio.h>
#include<stdlib.h>
typedef int Tp;
//链表
typedef struct node
{
Tp data;
struct node * ltree, *rtree;
}Node,*Tree;
//排序二叉树
typedef struct listnode
{
Tp data;
struct listnode * nextnode;
}lNode,*List;
//往排序二叉树送入值
bool insertTree(Tree * T, const Tp data)
{
Node * pnode = (Node*)malloc(sizeof(Node));
//printf("pnode add: %p\n", pnode);
pnode->data = data;
pnode->ltree = NULL;
pnode->rtree = NULL;
if (!(*T))
{
*T = pnode;
return true;
}
else
{
if (pnode->data < (*T)->data )//若小于根节点值
{
if ((*T)->ltree)//若左子树不为空,继续递归
{
Node pnodecpy = *pnode;//由于要递归,防止内存泄漏,这里需要将申请的内存堆转移出来,然后清空这个堆内存
free(pnode);
pnode = NULL;
insertTree(&((*T)->ltree), pnodecpy.data);
}
else//若左子树为空,直接赋值
{
(*T)->ltree = pnode;
return true;
}
}
else if (pnode->data > (*T)->data)//若大于根节点值
{
if ((*T)->rtree)//若右子树不为空,继续递归
{
Node pnodecpy = *pnode;//由于要递归,防止内存泄漏,这里需要将申请的内存堆转移出来,然后清空这个堆内存
free(pnode);
pnode = NULL;
insertTree(&((*T)->rtree), pnodecpy.data);
}
else//若右子树为空,直接赋值
{
(*T)->rtree = pnode;
return true;
}
}
else
{
return true;
}
}
}
//在链表尾部插入新元素函数
bool inserList(List *list, Tp data)
{
lNode *datanode = (lNode*)malloc(sizeof(lNode));
datanode->data = data;
datanode->nextnode = NULL;
if (!(*list))//若链表为空
{
*list = datanode;
return true;
}
else//若链表不为空
{
if ((*list)->nextnode == NULL)//若插入为本链表的第二个元素
{
(*list)->nextnode = datanode;
return true;
}
else//若插入为本链表的第3个元素及以上,迭代至最后一个元素
{
lNode nodecpy = *datanode;
free(datanode);
datanode = NULL;
return inserList(&((*list)->nextnode), nodecpy.data);
}
}
}
//中序遍历二叉树函数,将遍历结果保存在一个链表里
bool inorderTraversal(Tree t, List *l)
{
if (!t)
{
//printf("树为空");
return false;
}
else
{
if (t->ltree==NULL&&t->rtree==NULL)
{
printf(" %d ", t->data);
return inserList(l, t->data);
}
else
{
inorderTraversal(t->ltree, l);//访问左子树
printf(" %d ", t->data);
bool i = inserList(l, t->data);//访问根节点
inorderTraversal(t->rtree, l);//访问右子树
return true;
}
}
}
int main()
{
Tree t = NULL;
List l = NULL;
//链表初始化
bool b = false;
b = insertTree(&t, 44);
b = insertTree(&t, 55);
b = insertTree(&t, 33);
b = insertTree(&t, 20);
b = insertTree(&t, 45);
b = insertTree(&t, 37);
printf("树的地:%p\n左子树地址:%p\n右子树地址:%p\n", t, t->ltree, t->rtree);
printf("\n中序遍历结果(从小到大):");
b = inorderTraversal(t, &l);
printf("\n中序遍历结果(保存在链表):");
printf("链表的头节点地址: %p\n", l);
system("pause");
return 0;
}
运行结果
一些思考
在递归前,若是涉及在堆空间上动态开辟内存(如本文代码
inserList()
insertTree()
函数的malloc操作),为了防止递归的过程中不断开辟新堆空间而造成的浪费和风险,须在递归前将申请的内存中的变量保存下来(栈),再去递归。从无到有生成一个动态的数据的函数,传入参数须传入二级指针,以实现
malloc
,因为malloc
须赋值返回给一个指针变量,即修改一个指针变量,众说周知,修改一个指针变量需传入指针的指针,即二级指针来修改。- 根据上一条的结论,若函数须读,可仅仅传入一个值(值传递),若函数须读写,可以考虑传入一个指针(指针传递),若写一个值,传入指针,若写一个指针(地址,原或为NULL),传入一个二级指针,以此类推。