二叉树的最近公共祖先|c语言题解

157 阅读3分钟

里面有一个,借助助队列的层次遍历建立二叉树,也很重要(还不确定对不对)

/* 
【问题描述】
奥班农种植土豆,每年秋天都能收获很多很多,假设每个土豆能产生两个后代土豆,如何帮奥班农判断两个土豆的最近共同祖先呢,上帝曾经说过:没有两个长得一模一样的土豆

【输入形式】
二叉树的层次序列(-1表示空树,-100表示输入结束),以及两个单独的值
*/
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define LIST_INIT_SIZE 100
#define STACK_INIT_SIZE 100
#define MAXQSIZE 100
typedef int Status;

typedef struct BiTNode{
 	int	data;
	struct BiTNode *lchild,*rchild;
}BiTNode, *BiTree;

typedef struct {
	BiTree *base;
	int front,rear;} SqQueue; //定义循环队列,存储Glist类型指针

void InitQueue(SqQueue &Q)
{	Q.base = (BiTree *)malloc(MAXQSIZE * sizeof(BiTree));
	Q.front = Q.rear = 0;
}

Status EnQueue(SqQueue &Q, BiTree e)
{	if((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR;	//队满
	Q.base[Q.rear] = e;
	Q.rear = (Q.rear + 1) % MAXQSIZE;
	return OK;
}

Status DeQueue(SqQueue &Q, BiTree &e)
{	if(Q.rear == Q.front) return ERROR;	//队空
	e = Q.base[Q.front];
	Q.front = (Q.front + 1) % MAXQSIZE;
	return OK;
}

Status QueueEmpty(SqQueue Q)
{	if(Q.rear == Q.front) return TRUE;
	else	return FALSE;
}



//借助队列的,层次遍历,建立二叉树
void CreateBiTree(BiTree &T) {
    int val;
    // 读取根节点的值
    scanf("%d", &val);
    if (val == -1) {
        T = NULL; // 如果根节点的值为 -1,则表示空树
    } else {
        // 创建根节点
        T = (BiTNode *)malloc(sizeof(BiTNode));
        T->data = val;
        SqQueue Q;
        InitQueue(Q);
        EnQueue(Q, T);
        while (1) {
            // 从队列中取出一个节点
            BiTree p;
            DeQueue(Q, p);
            // 输入左子树的值
            scanf("%d", &val);
            if (val != -1 && val != -100) {
                // 创建左子树节点并加入队列
                p->lchild = (BiTNode *)malloc(sizeof(BiTNode));
                p->lchild->data = val;
                EnQueue(Q, p->lchild);
            } else {
                p->lchild = NULL;
            }
            // 输入右子树的值
            scanf("%d", &val);
            if (val != -1 && val != -100) {
                // 创建右子树节点并加入队列
                p->rchild = (BiTNode *)malloc(sizeof(BiTNode));
                p->rchild->data = val;
                EnQueue(Q, p->rchild);
            } else {
                p->rchild = NULL;
            }
            if (val == -100) {
                break; // 输入结束
            }
        }
        // 释放队列空间
        free(Q.base);
    }
}


//按层次遍历二叉树
void LevelOrderTraverse(BiTree T)
{	BiTree p = T;
	SqQueue Q;

	if(!T) return;
	InitQueue(Q); EnQueue(Q,p);
	while (!QueueEmpty(Q))
	{	DeQueue(Q,p);
		printf("%d ", p->data);
		if(p->lchild) EnQueue(Q,p->lchild);
		if(p->rchild) EnQueue(Q,p->rchild);
	}
}

void PreOrderTraverse(BiTree T)
{   if(T)
	{   printf("%d ", T->data);
	    PreOrderTraverse(T->lchild);
            PreOrderTraverse(T->rchild);
	}
}

void InOrderTraverse(BiTree T)
{   if(T)
	{   InOrderTraverse(T->lchild);
            printf("%d ", T->data);
	    InOrderTraverse(T->rchild);
	}
}

//求两个节点的最近公共祖先
BiTree findLCA(BiTree T,int n1, int n2) {
    if(T == NULL) return NULL;
    if(T->data == n1 || T->data == n2) return T;
    BiTree left = findLCA(T->lchild, n1, n2);
    BiTree right = findLCA(T->rchild, n1, n2);
    if(left != NULL && right != NULL) return T;
    if(left == NULL && right != NULL) return right;
    if(left != NULL && right == NULL) return left;
    return NULL;
}

int main() {
    BiTree T;                                
	CreateBiTree(T);
	printf("\n先序序列:"); PreOrderTraverse(T);

	printf("\n中序序列:");InOrderTraverse(T);                          

       printf("\n层次序列:");LevelOrderTraverse(T);
 	
    //printf("\n请输入两个土豆,去找他们的最近共同祖先:");
	int n1,n2;
       scanf("%d %d",&n1,&n2);

       BiTree lca = findLCA(T, n1,n2);
    
       if (lca) 
           printf("\n最近共同祖先是:%d\n",lca->data);
       else  printf("无祖先");
    
    return 1;
}

// 二叉树例
//       1
//      / \  
//     2   3  
//    / \   \ 
//   4   5   7
//     /  
//    10 
//层次序列:1 2 3 4 5 -1 7 -1 -1 10 -100
//8 6 -1 -1 7 3 4 -100