我为字符串创建了一个AVL树,树本身运行良好:插入,删除,搜索都运行良好。但是,valgrind给了我一个错误。 Valgrind说错误发生在我的stringDuplicate函数中(我已经对valgrind指出的特定行号做了评论),而且我的treeInsert函数调用了这个stringDuplicate函数(我在treeInsert调用stringDuplicate时发表了注释) 。有人能帮我找到我的valgrind错误吗?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "tree.h"
//NODES OF TREE
struct node{
char *word;
int balance;
struct node *children[2];
};
//STRUCT TREE WHICH CONTAINS A POINTER TO THE ROOT AND NUMBER OF ELEMENTS
struct tree{
struct node *root;
size_t numElements;
};
//MALLOC SPACE FOR TREE
struct tree *treeCreate(void){
struct tree *s = malloc(sizeof(struct tree));
s->root = NULL;
s->numElements = 0;
return s;
}
//CREATE A DUPLICATE OF THE STRINGS TO BE INSERTED/DELETED
char *stringDuplicate (const char *s) {
char *d = malloc (strlen (s) + 1); //VALGRIND POINTS TO THIS LINE FOR ERROR
if (d == NULL) return NULL;
strcpy (d,s);
return d;
}
//RETURN THE SIZE OF THE TREE
size_t treeSize(const struct tree *s){
return s->numElements;
}
//CREATE A NEW NODE OF THE TREE
struct node *make_node(char *word){
struct node *temp = malloc(sizeof(struct node));
if(temp != NULL){
temp->word = word;
temp->children[0] = temp->children[1] = NULL;
temp->balance = 0;
}
return temp;
}
//CHANGE THE BALANCE OF NODE/NODES IN THE TREE
void adjustBalance(struct node *root, int direction, int temp_bal){
struct node *temp1 = root->children[direction];
struct node *temp2 = temp1->children[!direction];
if(temp2->balance == 0){
root->balance = temp1->balance = 0;
}else if(temp2->balance == temp_bal){
root->balance = -temp_bal;
temp1->balance = 0;
}else{
root->balance = 0;
temp1->balance = temp_bal;
}
temp2->balance = 0;
}
//SINGLE ROTATION OF TREE
struct node *singleRotation(struct node *root, int direction){
struct node *temp = root->children[!direction];
root->children[!direction] = temp->children[direction];
temp->children[direction] = root;
return temp;
}
//DOUBLE ROTATION OF TREE
struct node *doubleRotation(struct node *root, int direction){
struct node *temp = root->children[!direction]->children[direction];
root->children[!direction]->children[direction] = temp->children[!direction];
temp->children[!direction] = root->children[!direction];
root->children[!direction] = temp;
temp = root->children[!direction];
root->children[!direction] = temp->children[direction];
temp->children[direction] = root;
return temp;
}
//CHANGE THE BALANCE OF NODES WHEN INSERTING
struct node *insertBalance(struct node *root, int direction){
struct node *temp = root->children[direction];
int temp_bal;
if(direction == 0){
temp_bal = -1;
}else{
temp_bal = 1;
}
if(temp->balance == temp_bal){
root->balance = temp->balance = 0;
root = singleRotation(root, !direction);
}else{
adjustBalance(root, direction, temp_bal);
root = doubleRotation(root, !direction);
}
return root;
}
//INSERT INTO TREE RECURSIVELY
struct node *insertRecursive(struct node *root, char *word, int *flag){
if(root == NULL){
root = make_node(word);
}
else{
//IF word < root->word, WE NEED TO GO LEFT AND direction < 0
//IF word > root->word, WE NEED TO GO RIGHT AND direction > 0
int direction = strcmp(word, root->word);
if(direction > 0){
direction = 1;
}else if(direction < 0){
direction = 0;
}
root->children[direction] = insertRecursive(root->children[direction], word, flag);
if(!*flag){
if(direction == 0){
root->balance += -1;
}else{
root->balance += 1;
}
if(root->balance == 0){
*flag = 1;
}else if(abs(root->balance) > 1){
root = insertBalance(root, direction);
*flag = 1;
}
}
}
return root;
}
//SEARCH FOR A STRING IN TREE: 1 IF IN TREE, 0 IF NOT
int searchTree(struct node *root, char *word){
int flag = 0;
struct node *current = root;
while(!flag){
if(current){
int direction = strcmp(word, current->word);
if(direction == 0){
flag = 1;
break;
}else if(direction > 0){
direction = 1;
}else{
direction = 0;
}
current = current->children[direction];
}else{
break;
}
}
return flag;
}
//INSERT NEW ELEMENT INTO TREE
void treeInsert(struct tree *tree, const char *word){
char *newWord = stringDuplicate(word);
int flag = searchTree(tree->root, newWord);
int temp = 0;
if(flag == 0){
tree->root = insertRecursive(tree->root, newWord, &temp);
tree->numElements = tree->numElements + 1;
}
}
//CHANGE THE BALANCE OF NODES WHEN DELETING FROM TREE
struct node *deleteBalance(struct node *root, int direction, int *flag){
struct node *temp = root->children[!direction];
int temp_bal;
if(direction == 0){
temp_bal = -1;
}else{
temp_bal = 1;
}
if(temp->balance == -temp_bal){
root->balance = temp->balance = 0;
root = singleRotation(root, direction);
}else if(temp->balance == temp_bal){
adjustBalance(root, !direction, -temp_bal);
root = doubleRotation(root, direction);
}else{
root->balance = -temp_bal;
temp->balance = temp_bal;
root = singleRotation(root, direction);
*flag = 1;
}
return root;
}
//DELETE A STRING FROM TREE ITERATIVELY
void treeDelete(struct tree *tree, const char *word){
if(tree->root != NULL){
char *newWord = stringDuplicate(word);
struct node *iterator, *ancestor_array[32];
int ancestor_direction[32];
int current_index = 0;
int flag = 0;
iterator = tree->root;
for(;;){
if(iterator == NULL){
return;
}else if(strcmp(newWord, iterator->word) == 0){
tree->numElements = tree->numElements - 1;
break;
}
int direction = strcmp(word, iterator->word);
if(direction > 0){
direction = 1;
}else if(direction < 0){
direction = 0;
}
ancestor_direction[current_index] = direction;
ancestor_array[current_index++] = iterator;
iterator = iterator->children[ancestor_direction[current_index - 1]];
}
if(iterator->children[0] == NULL || iterator->children[1] == NULL){
int dir = iterator->children[0] == NULL;
if(current_index != 0){
ancestor_array[current_index - 1]->children[ancestor_direction[current_index - 1]] = iterator->children[dir];
}else{
tree->root = iterator->children[dir];
}
free(iterator);
}else{
struct node *heir = iterator->children[1];
ancestor_direction[current_index] = 1;
ancestor_array[current_index++] = iterator;
while(heir->children[0] != NULL){
ancestor_direction[current_index] = 0;
ancestor_array[current_index++] = heir;
heir = heir->children[0];
}
iterator->word = heir->word;
ancestor_array[current_index - 1]->children[ancestor_array[current_index - 1] == iterator] = heir->children[1];
free(heir);
}
while(--current_index >= 0 && !flag){
ancestor_array[current_index]->balance += ancestor_direction[current_index] != 0 ? -1 : 1;
if(abs(ancestor_array[current_index]->balance) == 1){
break;
}else if(abs(ancestor_array[current_index]->balance) > 1){
ancestor_array[current_index] = deleteBalance(ancestor_array[current_index], ancestor_direction[current_index], &flag);
if(current_index != 0){
ancestor_array[current_index - 1]->children[ancestor_direction[current_index - 1]] = ancestor_array[current_index];
}else{
tree->root = ancestor_array[0];
}
}
}
}
return;
}
//FREE TREE
void treeDestroyHelper(struct node *root){
if(root == NULL){
return;
}
if(root->children[0] == NULL && root->children[1] == NULL){
free(root->word);
free(root);
}else if(root->children[0] == NULL && root->children[1] != NULL){
treeDestroyHelper(root->children[1]);
free(root->word);
free(root);
}else if(root->children[0] != NULL && root->children[1] == NULL){
treeDestroyHelper(root->children[0]);
free(root->word);
free(root);
}else{
treeDestroyHelper(root->children[0]);
treeDestroyHelper(root->children[1]);
free(root->word);
free(root);
}
}
//FREE TREE
void treeDestroy(struct tree *s){
treeDestroyHelper(s->root);
free(s);
}
编辑:只是想添加注释,以防有人想知道tree.h只是我正在使用的函数头。
答案 0 :(得分:0)
您复制word
中的treeDelete()
并忘记释放它。那里没有必要复制。 valgrind抱怨stringDuplicate()
分配的内存未被释放。
顺便提一下,此功能名称令人困惑,您应该使用treeDeleteString
。 treeInsert
- &gt;相同treeInsertString
,以及其他一些。
修改:您还忘记在treeDelete()
和free(iterator);
之前释放free(heir);
中的字符串。我无法判断treeDelete()
中的逻辑是否通过对代码的快速分析是正确的,但这些缺失的free()
肯定会导致内存丢失并由valgrind报告。