文章目录
下面写的代码可能感觉会很乱,所以加上了目录,意在为了引导,也就是你需要回顾哪个算法,就能够快速定位到该位置。另外,线索二叉树只写了中序线索二叉树。
三、树和二叉树
(一)二叉树的顺序存储结构
- 二叉树的顺序存储结构最适用于存储完全二叉树,存储方法如下:
- 构造完全二叉树
int data[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
(二)二叉树的链式存储结构——二叉链表存储结构
- 结构体的声明
typedef struct BT_NODE
{
int data; //存放结点中的数据,这里的数据类型可以改变
struct BT_NODE* l_child; //指向左孩子的指针
struct BT_NODE* r_child; //指向右孩子的指针
}BT_NODE;
(三)二叉树的遍历算法
- 在遍历二叉树之前,我们是不是得要有一个二叉链表?下面是构造二叉链表代码
/*
method:
初始化一个树,用二叉链表表示,
param:
bt_node 树
data 这里是一个数组,数组里面的数据是按照完全二叉树的顺序存储结构存储的。
n 是要存储的结点的个数
pos 这里是当前结点位置,初始值为0
此方法大致思路如下:
1
2 3
4 5 6 7
8 9 10 11 12 13 14 15
存储顺序如下:1->2->4->8->9->5->10->11->3->6->12->13->7->14->15
即:每次先存储左孩子,直到最后左孩子的数组越界,然后返回上一层,存储右孩子
*/
int BT_Init(BT_NODE* bt_node, int* data, int n, int pos)
{
BT_NODE* p, * q;
if (n <= 0) //如果输入的个数n小于等于0,直接返回
return ERROR;
if (pos == 0) //因为递归,这个不能重复赋值,所以只在根节点也就是位置为0处,赋值
{
//目的只是为了执行一次
bt_node[0].data = data[0];
bt_node[0].l_child = NULL;
bt_node[0].r_child = NULL;
if (n == 1) //在这里加一个判断,如果输入值为1,返回创建成功
return OK;
}
/************************************************************/
/*************************创建树的核心代码*******************/
/************************************************************/
if(2 * pos + 1 >= n) //2*pos+1 的位置是它的左孩子的值在数组中存放位置。为了防止数组越界
return ERROR;
p = (BT_NODE*)malloc(sizeof(BT_NODE)); //创建内存
p->data = data[2 * pos + 1]; //获取数据
p->l_child = NULL;
p->r_child = NULL;
bt_node->l_child = p; //创建的左孩子将其当作子树的根节点,进行递归
BT_Init(bt_node->l_child, data, n, 2 * pos + 1); //这里是递归操作,意在每次都是先创建左子树,再创建右子树,
//直到左子树数组越界,然后返回上一层,创建右子树
if (2 * pos + 2 >= n)
return ERROR;
q = (BT_NODE*)malloc(sizeof(BT_NODE));
q->data = data[2 * pos + 2]; //2*pos+2 的位置是它的右孩子的值在数组中存放位置。为了防止数组越界
q->l_child = NULL;
q->r_child = NULL;
bt_node->r_child = q; //创建的右孩子将其当作子树的根节点,进行递归
BT_Init(bt_node->r_child, data, n, 2 * pos + 2); //这里是创建右侧分支的结点,仍然是先创建左子树,再创建右子树。
return OK;
}
- 访问二叉树
/*
method:
访问结点
param:
bt_node 二叉树
*/
void Visit(BT_NODE* bt_node)
{
printf("%d ", bt_node->data); //打印出来二叉树的结点值
}
- 先序遍历二叉树
/*
method:
先序遍历二叉树
param:
bt_node 二叉树
*/
void Preorder(BT_NODE* bt_node)
{
if (bt_node != NULL)
{
Visit(bt_node); //先访问根节点
Preorder(bt_node->l_child); //再访问左结点
Preorder(bt_node->r_child); //最后访问右结点
}
}
- 中序遍历二叉树
/*
method:
中序遍历二叉树
param:
bt_node 二叉树
*/
void Infix_Order(BT_NODE