假设二叉树采用二叉链表方式存储, root指向根结点,p所指结点和q所指结点为二叉树中的两个结点,编写一个计算它们的最近的共同祖先,函数定义如下:
BiTNode * nearest_ancestor(BiTree root, BiTNode *p, BiTNode *q);
其中 root 指向二叉树的根结点,p 和 q 分别指向二叉树中的两个结点。
提示:在完成本题时,可利用 path 函数获取p和q两个结点到根结点之间的路径,之后再计算两条公共路径得出最近的共同祖先。path函数及栈相关定义如下:
bool path(BiTNode* root, BiTNode* node, Stack* s);
#define Stack_Size 50
typedef BiTNode* ElemType;
typedef struct{
ElemType elem[Stack_Size];
int top;
}Stack;
void init_stack(Stack *S); // 初始化栈
bool push(Stack* S, ElemType x); //x 入栈
bool pop(Stack* S, ElemType *px); //出栈,元素保存到px所指的单元,函数返回true,栈为空时返回 false
bool top(Stack* S, ElemType *px); //获取栈顶元素,将其保存到px所指的单元,函数返回true,栈满时返回 false
bool is_empty(Stack* S); // 栈为空时返回 true,否则返回 false
BiTNode* nearest_ancestor(BiTree root, BiTNode* p, BiTNode* q)
{
int num1 = 0, num2 = 0;
BiTNode *node1[100], *node2[100];
Stack s1, s2;
init_stack(&s1);
init_stack(&s2);
path(root, p, &s1);
path(root, q, &s2);
while (!is_empty(&s1))
pop(&s1, &node1[num1++]);
while (!is_empty(&s2))
pop(&s2, &node2[num2++]);
if (num1 < num2)
for (int i = 0; i < num1; i++) {
if (node1[i] == node2[num2 - (num1 - i)])
return node1[i];
}
else
for (int i = 0; i < num2; i++) {
if (node2[i] == node1[num1 - (num2 - i)])
return node2[i];
}
}
思路:
利用path函数获得p、q分别到根结点的路径,并且将p与根节点(包括p与根节点在内)之间的所有结点pop到一个初始化后的栈中、将q与根节点(包括q与根节点在内的)之间的所有结点pop到另一个初始化好的栈中。
将两个栈中的元素分别给初始化好的两个指针数组
将num1>num2与num1<=num2两种情况分别考虑(防止num1-(num2+i)为负数)。因为栈的“后进先出”的特性,数组里下标小的元素更靠近栈顶,与p和q相差的结点数目越少,所以i从0开始计数。
(
for (int i = 0; i < num1; ++i) {
for (int j = 0; j < num2; ++j) {
if (Node1[i] == Node2[j]) {
return Node1[i];
这样写也可以,但是时间复杂度为n^2,比原代码中时间复杂度为n的代码执行效率低。(都能过)
#include
#include
#include
#define Stack_Size 50
typedef int DataType;
typedef struct Node {
DataType data;
struct Node* left=NULL;
struct Node* right=NULL;
}BiTNode,*BiTree;
typedef BiTNode* ElemType;
typedef struct {
ElemType elem[Stack_Size];
int top;
}Stack;
void init_stack(Stack* S) {
S->top = -1;
}
bool push(Stack* S, ElemType x) {
if (S->top == Stack_Size - 1)
return false;
S->top++;
S->elem[S->top] = x;
return true;
}
bool pop(Stack* S, ElemType* px) {
if (S->top == -1)
return false;
*px = S->elem[S->top];
S->top--;
return true;
}
bool top(Stack* S, ElemType* px) {
if (S->top == -1)
return false;
*px = S->elem[S->top];
return true;
}
bool is_empty(Stack* S) {
return(S->top == -1 ? true : false);
}//作为一个判断条件
bool path(BiTNode* root, BiTNode* node, Stack* s) {
BiTree T = root, p;
if (T == NULL || node == NULL || !is_empty(s))
return false;
while (T||!is_empty(s)) {
while (T) {
push(s, T);
if (T == node)
return true;
T = T->left;
}
top(s,&T);
if (!T->right || T->right == p) {
p = T;
pop(s, &T);
T = NULL;
}
else T = T->right;
}
return false;
}
void init_tree(BiTree* node) {
*node = (BiTree) malloc(sizeof(BiTNode));
DataType value;
DataType left, right;
scanf("%d %d %d",&value,&left,&right);
(*node)->data = value;
if (left) init_tree(&(*node)->left);
else (*node)->left = NULL;
if (right) init_tree(&(*node)->right);
else (*node)->right = NULL;
}
BiTNode* nearest_ancestor(BiTree root, BiTNode* p, BiTNode* q) {
int num1 = 0, num2 = 0;
BiTNode* node1[100],*node2[100];
Stack s1, s2;
init_stack(&s1);
init_stack(&s2);
path(root, p, &s1);
path(root, q, &s2);
while (!is_empty(&s1))
pop(&s1, &node1[num1++]);
while (!is_empty(&s2))
pop(&s2,&node2[num2++]);
if(num1<num2)
for (int i = 0;i < num1;i++) {
if (node1[i] == node2[num2 - (num1- i)])
return node1[i];
}
else
for (int i = 0;i < num2;i++) {
if(node2[i]==node1[num1-(num2-i)])
return node2[i];
}
}
BiTNode* Node(BiTree root, int dat) {
if (root == NULL) return NULL;
if (root->data == dat) return root;
BiTree res;
if (res = Node(root->left, dat)) return res;
if (res = Node(root->right, dat)) return res;
return NULL;
}
int main(void) {
freopen("in.txt","r",stdin);
BiTree a;
init_tree(&a);
BiTNode* p, * q;
int data1, data2;
scanf("%d %d", &data1, &data2);
p = Node(a, data1);
q = Node(a, data2);
BiTNode* anc = nearest_ancestor(a, p, q);
printf("%d\n", anc->data);
return 0;
}
typedef struct Node {//用栈初始化变量
DataType data;
struct Node* left=NULL;
struct Node* right=NULL;
}BiTNode,*BiTree;
void init_tree(BiTree* node) {//用堆初始化变量
*node = (BiTree) malloc(sizeof(BiTNode));
DataType value;
DataType left, right;
scanf("%d %d %d",&value,&left,&right);
(*node)->data = value;
if (left) init_tree(&(*node)->left);
else (*node)->left = NULL;
if (right) init_tree(&(*node)->right);
else (*node)->right = NULL;
}
用堆初始化变量:初始化的变量所分配的内存时跟变量size相同的内存空间。
用栈和用堆初始化变量的标志:
用栈初始化变量没有调用malloc()函数,而用堆初始化调用了malloc()函数。
2. 编写一个通过值查找节点的函数
3.调试顺序