一,二叉树的结构
类似与双向链表的前驱后继。
结构:中间data存数据,left指向左边,right指向右边(结构就不多讲)
二,迷幻的存入一串数字
正常不论将数据存入数组还是链表,都是需要几个存入几个;
但是树的存入数据要多输入的要比实际存入的数多叶子的两倍。
如上图,想要存入7个数据实际就要输入7+4*2=15个数据
存入的方法为先存取左边,结束后再右边存取(递归)
代码:
Node* init()
{
Node *p;
int c;
scanf_s("%d", &c);
if (c == 0) //等于0代表当前地方结束存入
p = NULL;
else
{
p = new Node;
p->data = c; //等待返回
p->left = init(); //先存左边的数(递归)
p->right = init(); //再存取右边的数
}
return p;
}
运行截图
如图输入才能将7个数输入进去;
第一行的1代表根
先根结点1的左边 : 第三行的2代表根结点1的左分支
再结点2的左边: 第四行的3是2的左分支,后面的两个零代表3后面的左右分支都为空,结束
再结点2的右边: 第五行的4是2的右分支,后面的两个零代表4后面的左右分支都为空,结束
根节点的左分支结束
先根结点1的右边 : 第七行的5代表根结点1的右分支
再结点5的左边: 第八行的6是5的左分支,后面的两个零代表6后面的左右分支都为空,结束
再结点5的右边: 第九行的7是5的右分支,后面的两个零代表7后面的左右分支都为空,结束
右边存取结束,整串数字存入到二叉树中了
三,遍历(前序,中序,后序)
前序遍历:中间->左边->右边 (中左右)
中序遍历:左边->中间->后面 (左中右)
后序遍历:左边->右边->中间 (左右中)
哪一种方法,方法的名字在三个顺序的中间
遍历的方法为递归
即:三种方法函数的不同之处即为顺序不同
前:
cout << root->data << " ";
show(root->left);
show(root->right);
中:
show(root->left);
cout << root->data << " ";
show(root->right);
后:
show(root->left);
show(root->right);
cout << root->data << " ";
代码:
四,线索二叉树(称之为最废)
网上搜了好久关于线索二叉树的作用,得到的唯一的作用就是,遍历可以不用递归,直接遍历完(感觉没什么用)。
结构(比上面多了两个结点)
原因:
因为二叉树的左右结点为空时,会浪费资源,所以新加两个定义来判断左右结点是否为空;
当左或者右结点为空时,指向前驱或者后继.
此时用lT和rT判断
lT=0:指向左节点
lT=1:指向前驱
rT=0:指向右节点
rT=1:指向后继
下图可见:
图中二叉树是满二叉树,1,2,5有左右,所以1,2,5的lT和rT都为0,左右分别指向左右节点。
最下面一行叶都没有左右,所以3,4,6,7的lT和rT都为1,所以左右分别指向前驱后继(head指前驱,next指后继)
图解:
代码:
将二叉树中序线索化
void xiansuo(Node *root)
{
if (root)
{
xiansuo(root->left);
if (root->left == NULL)
{
root->lT = 1;
root->left = pre; //定义的全局变量
}
else
{
root->lT = 0;
}
if (pre->right == NULL)
{
pre->rT = 1;
pre->right = root;
}
else
{
pre->rT = 0;
}
pre = root;
xiansuo(root->right);
}
}
将二叉树中序输出:
void show(Node *root)
{
while (root)
{
while (root->lT == 0){
root = root->left;
}
cout<<root->data;
while (root->rT == 1 && root->right != NULL)
{
root = root->right;
cout<<root->data;
}
root = root->right;
}
}