#include <bits/stdc++.h>
#define MAX 1000
using namespace std;
typedef struct node
{
int INFO;
struct node *LLINK, *RLINK; //用指针的原因 该结构体还未建成
} T;
//8.思路:在遍历结点时对其进行判定
void BianLi(T *root)
{
static int num = 0; //这里设置为静态变量 函数结束内存不会释放
if (root)
{
if (root->LLINK && root->RLINK)
num++;
BianLi(root->LLINK);
BianLi(root->RLINK);
}
}
//9.思路:对根节点先改变左右孩子 再进行遍历
void Change(T *root)
{
if (root)
{
T *temp = root->LLINK;
root->LLINK = root->RLINK;
root->RLINK = temp;
Change(root->LLINK);
Change(root->RLINK);
}
}
//10.思路:在先序遍历的基础上修改 将遍历的代码改成判断代码
int k; //在调用函数前进行赋值
void BianLi(T *root)
{
static int num = 0; //这里设置为静态变量 函数结束内存不会释放
if (root)
{
num++;
if (num == k)
printf("%d\n", root->INFO);
BianLi(root->LLINK);
BianLi(root->RLINK);
}
}
//11.思路:在遍历时进行判定 相等就删除并标记其后代 不等继续遍历
int x; //调用函数前赋值
void Delet(T *root, bool flag)
{ //flag为标记 true表示该删
if (root)
{
if (root->INFO == x || flag)
{ //满足条件或该删
Delet(root->LLINK, true);
Delet(root->RLINK, true);
delete root; //对应创建空间的代码 这里对应 new
}
else
{
Delet(root->LLINK, false);
Delet(root->RLINK, false);
}
}
}
//12.思路:没说是链式 采用数组
int Tree[MAX]; //调用函数前赋值
void print(int x, int n)
{ // n表示使用数组空间最大值
int k = 0;
for (int i = 0; i < n; i++)
{ //找x
if (Tree[i] == x)
{
k = i;
break;
}
}
int mystack[MAX], len = 0;
while (k)
{//模拟入栈
k /= 2; //利用了二叉树的特性
mystack[len++] = Tree[k];
}
for (int i = len - 1; i >= 0; i--) //正向输出其祖先
printf("%d ", mystack[i]);
}
/**
注:
后序非递归遍历的过程中,
栈中保留的是当前结点的所有祖先。
这是和先序及中序遍历不同的。
在某些和祖先有关的算法中,此算法很有价值。
**/
//13.思路:利用递归即栈的特性 若采取后续遍历 则遍历该节点时栈内全为其父结点
T *Ancestor(T *root, T *p, T *q)
{
int mystack_n = 0, mystack1_n = 0, mystack2_n = 0;
T *mystack[MAX], *mystack1[MAX], *mystack2[MAX];
T *temp = root, *record = NULL;
while (temp || mystack_n)
{
if (temp)
{//一直找左孩子并入栈
mystack[mystack_n++] = temp;
temp = temp->LLINK;
}
else
{
temp = mystack[mystack_n - 1];//取栈头
if (temp->INFO == p->INFO)
{ //找到p结点 就把栈复制 来存储p的祖先
for (int i = 0; i < mystack_n; i++)
mystack1[i] = mystack[i];
mystack1_n = mystack_n;
}
if (temp->INFO == q->INFO)
{ //找到q结点 就把栈复制 来存储q的祖先
for (int i = 0; i < mystack_n; i++)
mystack2[i] = mystack[i];
mystack2_n = mystack_n;
}
if (temp->RLINK && temp->RLINK != record)
{
temp = temp->RLINK; //到了没左孩子的时候走右孩子
mystack[mystack_n++] = temp;
temp = temp->LLINK; //temp已更新 可能存在左孩子
}
else
{
mystack_n--; //退栈
record = temp; //记录访问的结点用来防止重复入栈
temp = NULL; //下次访问时直接退栈
}
}
}
T *r = NULL;
for (int i = mystack2_n - 1; i >= 0; i--)
{
for (int j = mystack1_n; j >= 0; j--)
{
if (mystack2[i]->INFO == mystack1[j]->INFO)
{ //对比两个栈的元素 本质是比较两个结点的祖先
r = mystack1[j];
break;
}
}
}
return r;
}
//14.思路:在层次遍历时记录每层的结点数 注意要在每层最后一个结点将数置零
int Width(T *root)
{
int max = 0, num = 0;
if (root)
{
int myqueue_h = 0, myqueue_t = 0;
T *myqueue[MAX]; //模拟队列
T *p, *q, *last = root; //工作指针 标记指针 每层最后的指针
myqueue[myqueue_t++] = root; //先让根入队列
while (myqueue_h != myqueue_t)
{
p = myqueue[myqueue_h++]; //去队列的头
if (p->LLINK)
{
myqueue[myqueue_t++] = p->LLINK;
q = p->LLINK;
num++;
}
if (p->RLINK)
{
myqueue[myqueue_t++] = p->RLINK;
q = p->RLINK;
num++;
}
if (p == last)
{ //判定是否为每层最后结点
last = q;
if (num > max)
max = num;
num = 0;
}
}
}
return max;
}
//15.思路:利用满二叉树的特点
void PreToPost(int pre[], int low1, int high1, int post[], int low2, int high2)
{
if (high1 >= low1)
{
post[high2] = pre[low1];
int half = (high1 - low1) / 2; //在pre数组里half为前半部分 在post数组中为后半部分
PreToPost(pre, low1 + 1, low1 + half, post, low2, low2 + half - 1);
//去头后 数组pre的前半段是数组post数组的前半段去尾
PreToPost(pre, low1 + half + 1, high1, post, low2 + half, high2 - 1);
//数组pre的后半段是数组post数组的后半段去尾
}
}
//16.思路:同8 在遍历时进行叶子结点的判定并操作
T *head, *q;
void BianLi(T *root)
{
if (root)
{
if (!root->LLINK && !root->RLINK)
{ //当左右孩子都是空的
if (!head)
{ //插头
head = root;
q = head;
}
else
{ //链表插入
q->RLINK = root;
q = root;
}
}
BianLi(root->LLINK);
BianLi(root->RLINK);
}
}
//17.思路:直接递归模拟
bool Similar(T *root1, T *root2)
{
if (root1 == NULL && root2 == NULL)
return true; //空树
else if (root1 == NULL || root2 == NULL)
return false; //除了全空的话 有一个空就不相似
else
return Similar(root1->LLINK, root2->LLINK) && Similar(root1->RLINK, root2->RLINK);
}
二叉树的基本操作————数据结构//复习复习复习
于 2021-11-24 21:52:53 首次发布