我有一个程序正在尝试编译,但它向我显示编译错误:
at line 266 : invalid operands to binary !=
。代码如下:
程序接收两个二叉树作为参数,当树包含完全相同的值并具有相同的层次结构时,必须返回 true。
第 266 行:
} else if (arv1->item != arv2->item) {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef int TIPOCHAVE;
typedef enum { NoEsquerdo, NoDireito, NoPai, NoRaiz } DIRECAO;
typedef struct {
TIPOCHAVE chave;
// char valor[100];
} ITEM;
typedef struct estrutura
{
ITEM item;
struct estrutura *esq;
struct estrutura *dir;
struct estrutura *pai;
} ARVORE_BINARIA;
// Inicializa a arvore binaria deixando-a pronta para ser utilizada.
void inicializar(ARVORE_BINARIA *arvore)
{
arvore = NULL;
}
// Retorna true se a arvore esta vazia (igual a NULL)
bool vazia(ARVORE_BINARIA *arvore)
{
return arvore == NULL;
}
// Cria um novo no usando o apontador arvore passado contendo o item,
// os apontadores para o pai e para os filhos contendo NULL
void criarNo(ITEM item, ARVORE_BINARIA **arvore)
{
if (!vazia(*arvore))
{
printf("ERRO: O no deve estar vazio para ser criado.");
exit(EXIT_FAILURE);
}
*arvore = (ARVORE_BINARIA*) malloc(sizeof(ARVORE_BINARIA));
(*arvore)->item = item;
(*arvore)->pai = NULL;
(*arvore)->esq = NULL;
(*arvore)->dir = NULL;
}
// Testa se o No indicado por Direcao a partir de arv existe
bool existeNo(DIRECAO direcao, ARVORE_BINARIA *arvore)
{
if (vazia(arvore))
return false;
if (direcao == NoRaiz)
return true;
if (direcao == NoPai)
return !vazia(arvore->pai);
if (direcao == NoEsquerdo)
return !vazia(arvore->esq);
if (direcao == NoDireito)
return !vazia(arvore->dir);
return false;
}
// Deslocar o apontador Arvore para o No indicado por Direcao
void deslocar(DIRECAO direcao, ARVORE_BINARIA **arvore)
{
if (direcao == NoRaiz)
while (existeNo(NoPai, *arvore))
*arvore = (*arvore)->pai;
if (direcao == NoPai)
*arvore = (*arvore)->pai;
if (direcao == NoEsquerdo)
*arvore = (*arvore)->esq;
if (direcao == NoDireito)
*arvore = (*arvore)->dir;
}
/*
Objetivo: O parametro item recebe o item contido no No apontado por Arvore.
Caso tenha sucesso, retorna true. Caso contr�rio, false.
*/
bool obterItem(ITEM *item, ARVORE_BINARIA *arvore)
{
if (vazia(arvore))
return false;
*item = arvore->item;
return true;
}
/*
Objetivo: Altera o valor do item armazenado no No da Arvore.
Caso tenha sucesso, retorna true. Caso contr�rio, false.
*/
bool alterarItem(ITEM item, ARVORE_BINARIA *arvore)
{
if (vazia(arvore))
return false;
arvore->item = item;
return true;
}
// Cria um filho no NO apontado por Arvore na direcao informada
bool adicionarFilho(ITEM item, DIRECAO direcao, ARVORE_BINARIA *arvore)
{
if (vazia(arvore) || (direcao == NoPai) || (direcao == NoRaiz) || existeNo(direcao, arvore))
return false; // Criacao ilegal de um filho
if (direcao == NoEsquerdo)
{
criarNo(item, &(arvore->esq));
arvore->esq->pai = arvore;
}
else
{
criarNo(item, &(arvore->dir));
arvore->dir->pai = arvore;
}
return true;
}
// Desaloca da memoria toda a arvore
void disposeArvore(ARVORE_BINARIA *arvore)
{
if (!vazia(arvore))
{
disposeArvore(arvore->esq);
disposeArvore(arvore->dir);
free(arvore);
}
}
/*
| Objetivos: Desaloca da memoria arvore e seus descendentes, atualizando, se
| necessario, o apontador do pai dessa arvore ou atribuindo o valor
| NULL a arvore, quando for a raiz.
*/
void deltree(ARVORE_BINARIA **arvore)
{
ARVORE_BINARIA *pTemp = *arvore;
/*
Testa se Arvore tem pai. Caso tenha, arvore se desloca para ele e pTemp
continua apontando para o inicio da arvore a ser deletada, depois a
arvore e apagada e o apontador do pai e atualizado com NULL. Caso Arvore
nao tenha pai, a arvore e eliminada usando pTemp e arvore recebe NULL */
if (existeNo(NoPai, *arvore))
{
deslocar(NoPai, arvore);
disposeArvore(pTemp);
if ((*arvore)->esq == pTemp)
(*arvore)->esq = NULL;
else
(*arvore)->dir = NULL;
}
else
{
disposeArvore(pTemp);
arvore = NULL;
}
}
/*
| Objetivos: Percorre a arvore, visitando primeiro a raiz, depois a subarvore
| esquerda e por ultimo a subarvore direita.
*/
void preOrdem(ARVORE_BINARIA *arvore, void (*visite)(ARVORE_BINARIA*) )
{
if (!vazia(arvore))
{
visite(arvore);
preOrdem(arvore->esq, visite);
preOrdem(arvore->dir, visite);
}
}
/*
| Objetivos: Percorre a arvore, visitando primeiro a subarvore esquerda,
| depois a raiz e por ultimo a subarvore direita.
*/
void inOrdem(ARVORE_BINARIA *arvore, void (*visite)(ARVORE_BINARIA*) )
{
if (!vazia(arvore))
{
inOrdem(arvore->esq, visite);
visite(arvore);
inOrdem(arvore->dir, visite);
}
}
/*
| Objetivos: Percorre a arvore, visitando primeiro a subarvore esquerda,
| depois subarvore direita e por ultimo a a raiz.
*/
void posOrdem(ARVORE_BINARIA *arvore, void (*visite)(ARVORE_BINARIA*) )
{
if (!vazia(arvore))
{
posOrdem(arvore->esq, visite);
posOrdem(arvore->dir, visite);
visite(arvore);
}
}
/////////////////////////////////////////////////////
// Visita um NO da arvore, imprimindo o valor da chave
// entre parenteses
void visite(ARVORE_BINARIA *arvore) {
printf("(%d)", arvore->item.chave);
}
/////////////////////////////////////////////////////
/*
Objetivo: Retorna true quando os itens sao iguais e false quando
ha alguma diferenca.
*/
bool itensIguais(ITEM item1, ITEM item2)
{
return item1.chave == item2.chave;
}
/*
Objetivo: Dada duas arvores arv1 e arv2, retorna true quando as
arvores sao exatamente iguais, em conteudo e disposicao.
*/
bool iguais(ARVORE_BINARIA *arv1, ARVORE_BINARIA *arv2)
{
if (arv1 == NULL && arv2 == NULL) {
return true;
} else if (arv1 == NULL || arv2 == NULL) {
return false;
} else if (arv1->item != arv2->item) {
return false;
} else {
bool esquerda_iguais = iguais(arv1->esq, arv2->esq);
bool direita_iguais = iguais(arv1->dir, arv2->dir);
return esquerda_iguais && direita_iguais;
}
}
/////////////////////////////////////////////////////
// Mostra na tela uma linha informando se as Arvores sao iguais ou diferentes
void saoIguais(ARVORE_BINARIA *arv1, ARVORE_BINARIA *arv2) {
if (iguais(arv1, arv2))
printf("Arvores iguais\n");
else
printf("Arvores diferentes\n");
}
int main()
{
ARVORE_BINARIA *arv1 = NULL;
ARVORE_BINARIA *arv2 = NULL;
inicializar(arv1);
inicializar(arv2);
saoIguais(arv1, arv2); // iguais
ITEM item;
item.chave = 1;
criarNo(item, &arv1); // cria o no Raiz
saoIguais(arv1, arv2); // diferentes
criarNo(item, &arv2); // cria o no Raiz
saoIguais(arv1, arv2); // iguais
item.chave = 2;
adicionarFilho(item, NoEsquerdo, arv1);
saoIguais(arv1, arv2); // diferentes
adicionarFilho(item, NoEsquerdo, arv2);
saoIguais(arv1, arv2); // iguais
item.chave = 5;
adicionarFilho(item, NoDireito, arv1);
saoIguais(arv1, arv2); // diferentes
adicionarFilho(item, NoDireito, arv2);
saoIguais(arv1, arv2); // iguais
/*
1
2 5
*/
item.chave = 3;
adicionarFilho(item, NoEsquerdo, arv1->esq);
saoIguais(arv1, arv2); // diferentes
adicionarFilho(item, NoEsquerdo, arv2->esq);
saoIguais(arv1, arv2); // iguais
item.chave = 4;
adicionarFilho(item, NoDireito, arv1->esq);
saoIguais(arv1, arv2); // diferentes
adicionarFilho(item, NoDireito, arv2->esq);
saoIguais(arv1, arv2); // iguais
item.chave = 6;
adicionarFilho(item, NoEsquerdo, arv1->dir);
saoIguais(arv1, arv2); // diferentes
adicionarFilho(item, NoEsquerdo, arv2->dir);
saoIguais(arv1, arv2); // iguais
item.chave = 7;
adicionarFilho(item, NoDireito, arv1->dir->esq);
saoIguais(arv1, arv2); // diferentes
adicionarFilho(item, NoDireito, arv2->dir->esq);
saoIguais(arv1, arv2); // iguais
/*
1
2 5
3 4 6
7
*/
disposeArvore(arv1);
disposeArvore(arv2);
return 0;
}
item
是一个结构。在 C 语言中,您不能使用 ==
和 !=
等比较运算符相互比较 struct:s。
您可以编写一个函数来逐个比较两个结构体。
数据成员项具有结构类型
typedef struct estrutura
{
ITEM item;
struct estrutura *esq;
struct estrutura *dir;
struct estrutura *pai;
} ARVORE_BINARIA;
C中没有为结构类型的对象定义相等运算符==。所以编译器报错。您需要将结构类型成员的对象与成员进行比较。
还有这个功能
// Inicializa a arvore binaria deixando-a pronta para ser utilizada.
void inicializar(ARVORE_BINARIA *arvore)
{
arvore = NULL;
}
没有意义,因为它改变了它的局部变量(参数)
arvore
但不是在 main 中声明并由参数表达式使用的指针。
所以在这些语句中调用函数
ARVORE_BINARIA *arv1 = NULL;
ARVORE_BINARIA *arv2 = NULL;
inicializar(arv1);
inicializar(arv2);
没有效果。指针
arv1
和arv2
已经设置为NULL
并且函数处理指针值的副本。
在函数中
iguais
这段代码片段
} else {
bool esquerda_iguais = iguais(arv1->esq, arv2->esq);
bool direita_iguais = iguais(arv1->dir, arv2->dir);
return esquerda_iguais && direita_iguais;
}
可以像这样更简单地重写
} else {
return iguais(arv1->esq, arv2->esq) && iguais(arv1->dir, arv2->dir);
}
这使得它更有效率,因为在这行原始代码片段中调用了函数
bool direita_iguais = iguais(arv1->dir, arv2->dir);
将被跳过。
并使用英文单词作为标识符。在这种情况下,您的代码将更具可读性。