Estructura de datos --- Suplemento a las preguntas básicas de la entrevista

1. Problema de LeetCode 110: árbol binario equilibrado

Enlace: enlace .
Inserte la descripción de la imagen aquí
El valor absoluto de la diferencia de altura entre los subárboles izquierdo y derecho de cada nodo de un árbol binario no exceda 1 es un punto importante para la comprensión de esta cuestión.
Hay dos formas de resolver este problema ①Es equivalente a la idea de recorrido de preorden. Divídalo en el árbol actual, el subárbol izquierdo y el subárbol derecho, escriba las ideas del árbol actual y luego implemente la recursividad en el subárbol izquierdo y el subárbol derecho. Si los subárboles izquierdo y derecho del árbol actual no cumplen con las condiciones de un árbol binario equilibrado, a continuación, puede volver directamente falsa, y luego comenzar a juzgar si cada sub-árbol en el subárbol izquierdo corresponde a la definición de un árbol binario equilibrado. En En resumen, cada nodo de puntos se considera como un nodo raíz de un árbol binario para juzgar si cumple con la definición de un árbol binario equilibrado.

int TreeDepth(struct TreeNode* root)
{
    
    
    if(root == NULL)
        return 0;
    //为的就是消除代码冗余
    int leftDepth = TreeDepth(root->left);
    int rightDepth = TreeDepth(root->right);

//求出左右子树较大的哪一个
    return leftDepth > rightDepth? leftDepth+1 :rightDepth+1;

}

bool isBalanced(struct TreeNode* root){
    
    
    if(root == NULL)
       return true;
    //这样重新定义一个变量的目的就是消除代码的冗长
    int gap = TreeDepth(root->left)-TreeDepth(root->right);
    if(abs(gap) > 1)
        return false;

    return isBalanced(root->left) && isBalanced(root->right);
}

Pero encontrará que la complejidad temporal de un árbol binario autoequilibrado está entre O (N) ~ O (N * N) , siempre que la complejidad del tiempo transversal sea O (N), cuando ingrese y atraviese el subárboles izquierdo y derecho, no satisfarán la situación del árbol binario balanceado, pero cuando ha estado atravesando hasta que el último subárbol del subárbol derecho no cumple con la definición del árbol binario balanceado, básicamente el cálculo de la complejidad del tiempo satisface un secuencia aritmética, que es casi O (N * N), ** Entonces, ¿se puede optimizar? ** Encontrará esta idea de recorrido de preorden, habrá muchos cálculos repetidos de la altura del árbol. Entonces, usar el recorrido posterior aquí es más optimizado. Juzgará el árbol de la izquierda cuando ingrese, calculará la altura del último subárbol izquierdo en el árbol de la izquierda y devolverá verdadero o falso. En el mismo proceso de cálculo del árbol de la derecha, entonces encontrará cada uno de sus La altura de un árbol considerada por el nodo se calcula solo una vez, sin cálculos repetidos.

//一定要记住在你返回true的同时要返回一个高度值
bool _isBalanced(struct TreeNode* root,int* pDepth)
{
    
    
    //此时需要的是相当于后续遍历
    //先找到你最左边的树,再试最右边的树,在满足的同时返回true
    if(root == NULL)
    {
    
    
        *pDepth = 0;
        return true;
    }
    else
    {
    
    
        int leftDepth = 0;
        if(_isBalanced(root->left,&leftDepth) == false)
            return false;

        int rightDepth = 0;
        if(_isBalanced(root->right,&rightDepth) == false)
            return false;
        //走到这里说明左树和右树中所有的结点所对应小子树都是满足平衡二叉树的条件
        if(abs(leftDepth-rightDepth) > 1)
            return false;
        
        *pDepth = leftDepth > rightDepth?leftDepth+1:rightDepth+1;
        return true;
    }
}
bool isBalanced(struct TreeNode* root){
    
    
    int depth = 0;
    return  _isBalanced(root,&depth);
}

2. Niuke.com: recorrido de árbol binario

Enlace: enlace .
Inserte la descripción de la imagen aquí
De acuerdo con el recorrido en preorden y la entrada es ## g f ##, un árbol binario se puede dibujar abc ## de #.
Inserte la descripción de la imagen aquí

#include<stdio.h>
#include<stdlib.h>

typedef struct TreeNode {
    
    
     char val;
     struct TreeNode *left;
     struct TreeNode *right;
 }TreeNode;

TreeNode* CreateTree(char* str,int* pi)
{
    
    
    if(str[*pi] == '#')
    {
    
    
        (*pi)++;
        return NULL;
    }
    else
    {
    
    
        TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
        root->val = str[*pi];
        //构建左右子树
        (*pi)++;
        root->left = CreateTree(str,pi);
        root->right = CreateTree(str,pi);
        
        return root;
    }
}

void InOrder(TreeNode* root)
{
    
    
    if(root == NULL)
        return;
    InOrder(root->left);
    printf("%c ",root->val);
    InOrder(root->right);
}

int main()
{
    
    
    char str[100];
    scanf("%s ",str);
    
    int i = 0;
    TreeNode* root = CreateTree(str, &i);
    InOrder(root);
    return 0;
}

Al igual que LeetCode, Niuke.com necesita incluir archivos de encabezado y otro contenido por sí mismo. Dado que los discos de dibujo no son muy útiles, solo pueden usar capturas de pantalla para analizar aproximadamente este proceso recursivo. La siguiente figura es un análisis del proceso de construcción del árbol de la izquierda.
Inserte la descripción de la imagen aquí

3. Realización de la secuencia

La realización de la secuencia debe depender de la naturaleza de la cola, primero en entrar, primero en salir.
Inserte la descripción de la imagen aquí
Aquí también debe usar los archivos Queue.hy Queue.c originales, que se omiten aquí, pero debe agregar la declaración del archivo BTNode * en su Queue.h

Queue.h
//相当于把你的struct BinaryTreeNode拿过来申明一下
extern struct BinaryTreeNode;
typedef struct BinaryTreeNode*  QDateType;
//这里可以把BTNode的定义放到这里,但是这是一个Queue的头文件,有点挫


//二叉树的层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
    
    
	//在这里所定义的队列里面放的可不能只是值,那么你就在他出的时候找不到他的左右孩子入队列了
	Queue q;
	QueueInit(&q);
	if (root == NULL)
		return;
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
    
    
		BTNode* front = QueueFront(&q);
		//这里的Pop只是把这个数据从队列里面拿出来了,并没有删除
		QueuePop(&q);//从这个队列里面把这个结点拿出来
		printf("%c ", front->_date);
		if (front->_left)
		{
    
    
			QueuePush(&q, front->_left);
		}
		if (front->_right)
		{
    
    
			QueuePush(&q, front->_right);
		}
	}
	QueueDestory(&q);
	printf("\n");
}

3.1 ¿Es un árbol binario completo?

Con la ayuda de los pensamientos anteriores, la diferencia entre un árbol binario completo y un árbol binario incompleto es:
en el recorrido de la secuencia de capas,
si usted es un árbol binario completo, entonces todos sus nodos están reunidos en el frente (el nodo y su NULL están claramente separados)
Pero si usted es un árbol binario no completo, encontrará que su nodo puede contener NULL

//判断二叉树是否是一颗完全二叉树
//这个题借助上面的思想,完全二叉树和非完全二叉树的区别就是:
//在层序遍历中   
//如果你是完全二叉树那么你的结点都是聚集在前面的(结点和你的NULL是明显分割开的),
//但是如果你是非完全二叉树你会发现,你的结点中间可能包含了NULL
int BinaryTreeComplete(BTNode* root)
{
    
    
	Queue q;
	QueueInit(&q);
	if (root == NULL)
		return 1;  //是就返回1,不是返回0
	QueuePush(&q, root);

	//如果是完全二叉树,那么你的结点都出队列之后,队列就是NULL的
	//如果是非完全二叉树,当你遇见一个break之后,你去检查队列,你会发现队列是不为NULL的
	while (!QueueEmpty(&q))
	{
    
    
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front == NULL)
			break;


		QueuePush(&q, front->_left);
		QueuePush(&q, front->_right);
	}
	//此时上面已经遇见了一个空,再来判断队列里面剩下的
	while (!QueueEmpty(&q))
	{
    
    
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front)
		{
    
    
			QueueDestory(&q);
			return 0;
		}
	}
	//一定要记住放置内存泄漏,要对其所创建的队列进行释放
	QueueDestory(&q);
	return 1;
}

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/MEANSWER/article/details/112788445
Recomendado
Clasificación