Segmentation fault in hash table when inserting in linked list - c

I want to store passwords imput by user in a hash table by how strong the password is. After reading first password, it has to be inserted in the hash table and than go back for reading password. Segmentation fault occurs after first iteration.
The insertion function is basically an insertion in a linked list, what could be wrong there ?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Node{
char* str;
struct Node* next;
};
int procent(char* str){
char aux;
for(int i = 0; i < strlen(str)-1; i++){
for(int j = i+1; j < strlen(str); j++){
if(str[i] > str[j]){
aux = str[i];
str[i] = str[j];
str[j] = aux;
}
}
}
int count = 1, chr = str[0];
for(int i = 0; i < strlen(str); i++){
if(str[i] != chr){
count++;
chr = str[i];
}
}
return count;
}
int hash_function(char* str){
int len = strlen(str), index;
if(len < 5){
index = 0;
}
else if(index >= 5 && index < 8){
index = 1;
}
else if(index >= 8 && index < 12){
index = 2;
}
else{
index = 3;
}
float rap = procent(str)/strlen(str);
if(rap < 0.5 && index > 0){
index--;
}
else if(rap > 0.5 && index < 3){
index++;
}
return index;
}
void insert(struct Node** head, char* str){
printf("Error");
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
strcpy(new_node->str, str);
new_node->next = NULL;
if(*head == NULL){
*head = new_node;
return;
}
else{
struct Node* last_node = *head;
while(last_node->next != NULL){
last_node = last_node->next;
}
last_node->next = new_node;
}
}
int main(){
struct Node *H[4];
for(int i = 0; i < 4; i++){
H[i] = NULL;
}
int raspuns, rap;
char pass[20];
while(1){
printf("Mai citesti ? 1-da/0-nu: ");
scanf("%d",&raspuns);
if(raspuns == 1){
printf("Parola: ");
scanf("%s", pass);
rap = procent(pass)/strlen(pass);
insert(&H[rap], pass);
}
else{
break;
}
}
for(int i = 0; i < 4; i++){
switch(i){
case 0:{printf("Foarte slabe: "); break;}
case 1:{printf("Slabe: "); break;}
case 2:{printf("Puternice: "); break;}
case 3:{printf("Foarte puternice: "); break;}
default: break;
}
while(H[i] != NULL){
printf("%s", H[i]->str);
H[i] = H[i]->next;
}
printf("\n");
}
return 0;
}

Related

Parenthesis balance program crashing(c)

Good afternoon, i am trying to do a program that checks whether if a expression has its parentheses balanced or not but because of some problem that i can't quite find out the program is crashing, could somebody help me find a way so that the program works?
In
a * b - (2 + c)
Out
Correct
or
In
)3+b * (2-c)(
Out
Incorrect
The program should check only for parantheses and i am supposed to implement linear lists on the code.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SUCESSO 1 //Succes
#define FALHA -1 //Failure
#define CELULA_INVALIDA 0 //Invalid key
#define TAMANHO_MAXIMO 1000 //Max size
typedef struct{
char exp[1000];
unsigned int chave; //key
}celula; //node
typedef struct{
celula celulas[TAMANHO_MAXIMO]; //vector of nodes
unsigned int tamanho; //size of the list
}fila; //list
int criarFilaVazia(fila * ent){ //create an empty list
ent->tamanho = 0;
return(SUCESSO);
}
int insFinal(fila * ent, celula node){ //put a node on the end of the list
unsigned int i;
celula aux;
if(ent->tamanho == TAMANHO_MAXIMO){
return(FALHA);
}
else{
ent->celulas[ent->tamanho] = node;
ent->tamanho++;
return(SUCESSO);
}
}
void mostrarCelula(celula ent){ //show node
printf("%s \n", ent.exp);
}
void mostrarFila(fila ent){ //show entire list
unsigned int i;
if(ent.tamanho == 0){
printf("Fila vazia");
}
else{
printf("A fila possui %u element \n", ent.tamanho);
for(i=0; (i < ent.tamanho); i++){
printf("Elemento %u \n \n", (i+1));
mostrarCelula(ent.celulas[i]);
}
}
}
int main(){
int i, j;
fila exp;
celula aux;
scanf("%s", &aux.exp);
getchar();
aux.chave = 0;
insFinal(&exp, aux);
for(i = 0; i < strlen(exp.celulas[0].exp); i++){//checks all the array
if(exp.celulas[0].exp[i] == '('){//if there is an opening
for(j = i; j < strlen(exp.celulas[0].exp); j++){
if(exp.celulas[0].exp[j] == ')'){//should be and ending
exp.celulas[0].exp[i] = 0;//removes if balanced
exp.celulas[0].exp[j] = 0;
}
}
}
}
//checks for remaining parentheses and prints the output
for(i = 0; i < strlen(exp.celulas[0].exp); i++){
if(exp.celulas[0].exp[i] == '(' || exp.celulas[0].exp[i] == ')'){
printf("Incorreta"); //incorrect
}
else{
printf("Correta"); //correct
}
}
return 0;
}
[enter image description here][1]
Error message: https://i.stack.imgur.com/aeSn5.png
it says ex06 stopped working
Your program is crashing inside insFinal because the ent parameter passed in from main has uninitialized data. Hence, undefined behavior. Ammend these two lines at the beginning of main:
fila exp;
celula aux;
With this:
fila exp = {0};
celula aux = {0};
That will zero-init both.
The thing I don't get is what all these data structures are used for. Nor do I understand the double-nested for loop for checking the balance. Checking for a balanced set of parentheses in an expression should be as simple as this:
int areParenthesesBalanced(const char* str)
{
int balance = 0;
int len = str ? strlen(str) : 0;
for (int i = 0; i < len; i++)
{
if (str[i] == '(')
{
balance++;
}
else if (str[i] == ')')
{
balance--;
if (balance < 0)
{
return 0;
}
}
}
return (balance == 0) ? 1 : 0;
}
int main() {
char str[1000];
scanf("%s", str);
if (areParenthesesBalanced(str))
{
printf("Incorreta\n");
}
else
{
printf("Correta\n");
}
return 0;
}

remove element from pointer array in C

I'm trying to figure out why I cannot delete elements from the dict array. Could somebody help me out? The function removeWord is working as it is supposed to when removing the last added word, but not when trying to remove some other word.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NUMBER_OF_WORDS 11
int clear(){
while(getchar()^'\n');
return 0;
}
int numberOfWordsInDict(char **dict){
int i = 0;
int c1 = 0;
for (i = 0; i < MAX_NUMBER_OF_WORDS; ++i){
if (dict[i] != 0){
c1++;
}
}
return c1;
}
void addWord(char **dict, char *word){
int c1 = numberOfWordsInDict(dict);
char *word1;
if (c1 >= 0 && c1 < 10){
word1 = (char*) malloc(sizeof(char)*(strlen(word)+1));
dict[c1] = word1;
strncpy(dict[c1], word, strlen(word));
dict[c1][strlen(word)] = '\0';
} else if (c1 >= 10){
printf("Dictionary is already full!\n");
}
}
void printDict(char **dict){
int i = 0;
int c1 = numberOfWordsInDict(dict);
printf("Dictionary:\n");
if (c1 == 0){
printf("The dictionary is empty.\n");
} else if (c1 > 0 && c1 <= 10){
while (dict[i] != NULL){
printf("- %s\n", dict[i]);
i++;
}
}
}
void removeWord(char **dict, char *word){
int i = 0;
for (i = 0; i < MAX_NUMBER_OF_WORDS; i++){
if (strncmp(dict[i], word, strlen(word)+1) == 0){
dict[i] = 0;// can only delete the last element of dict properly.
break;
}
}
}
int main(){
char *dict[MAX_NUMBER_OF_WORDS] = {};
char word[1024] = {};
char command;
while(1){
printf("Command (a/p/r/q): ");
while(scanf("%s", &command) == 1){
break;
}
;
clear();
if (command == 'a'){ // add word
scanf("%[^\n]s", &word);
clear();
addWord(dict, word);
} else if (command == 'p'){ // print dict
printDict(dict);
} else if (command == 'r'){ // remove word
printf("Remove a word: ");
scanf("%[^\n]s", &word);
clear();
removeWord(dict, word);
} else if (command == 'q'){ // quit
break;
}
}
int i = 0;
for (i = 0; i < MAX_NUMBER_OF_WORDS; i++){
free(dict[i]);
}
return 0;
}
example input:
a
dog
a
cat
a
apple
case 1:
r
apple
p
// output =
Dictionary:
- dog
- cat
a
uniform
p
// output =
Dictionary:
- dog
- cat
- uniform
// works fine
case 2
r
cat
p
// output =
Dictionary:
- dog
a
book
p
// output =
Dictionary:
- dog
// doesn't work as expected
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NUMBER_OF_WORDS 11
int clear(){
while(getchar()^'\n');
return 0;
}
int numberOfWordsInDict(char **dict){
int c1 = 0;
for(int i = 0; i < MAX_NUMBER_OF_WORDS; ++i){
if (dict[i] != 0){
c1++;
}
}
return c1;
}
int vacancy(char **dict){
for(int i = 0; i < MAX_NUMBER_OF_WORDS; ++i){
if (dict[i] == 0){
return i;
}
}
return -1;
}
void addWord(char **dict, char *word){
int c1 = vacancy(dict);//It is not possible to use the registration number as an additional index.
if (-1 != c1){
dict[c1] = malloc(strlen(word)+1);
strcpy(dict[c1], word);
} else {
printf("Dictionary is already full!\n");
}
}
void printDict(char **dict){
int c1 = numberOfWordsInDict(dict);
printf("Dictionary:\n");
if (c1 == 0){
printf("The dictionary is empty.\n");
} else {
for(int i = 0; i < MAX_NUMBER_OF_WORDS; ++i){
if(dict[i])
printf("- %s\n", dict[i]);
}
}
}
void removeWord(char **dict, char *word){
for(int i = 0; i < MAX_NUMBER_OF_WORDS; i++){
if (strcmp(dict[i], word) == 0){
free(dict[i]);//need free
dict[i] = 0;// can only delete the last element of dict properly.
break;
}
}
}
int main(){
char *dict[MAX_NUMBER_OF_WORDS] = { NULL };
char word[1024] = { 0 };//forbids empty initializer braces
char command;
while(1){
printf("Command (a/p/r/q): ");
scanf("%c", &command);//%s buffer over run
clear();
if (command == 'a'){ // add word
scanf("%[^\n]", word);
clear();
addWord(dict, word);
} else if (command == 'p'){ // print dict
printDict(dict);
} else if (command == 'r'){ // remove word
printf("Remove a word: ");
scanf("%[^\n]", word);
clear();
removeWord(dict, word);
} else if (command == 'q'){ // quit
break;
}
}
int i = 0;
for (i = 0; i < MAX_NUMBER_OF_WORDS; i++){
free(dict[i]);
}
return 0;
}
Inside printDict() use
while (i<MAX_NUMBER_OF_WORDS){
if(dict[i] != 0)
printf("- %s\n", dict[i]);
i++;
}
instead of
while (dict[i] != NULL){
printf("- %s\n", dict[i]);
i++;
}
because even if you know if there are c1 number of words, you don't know their location as in where those c1 words are present.
Also change
while(scanf("%s", &command) == 1)
to
while(scanf("%c", &command) == 1)
since command is of char type.

Btree deletion code [duplicate]

Can anyone please help in removing this segmentation fault. I am working on this code for a week still unable to debug this. This code is a Btree implementation. The insertion part is working properly but there is an segmentation fault in deletion. I am unable to debug it, can anyone please help?
I have given the input based on this link (have converted alphabet value to ASCII value)
http://cis.stvincent.edu/html/tutorials/swd/btree/btree.html
When I delete the first H (equivalent ASCII value) it works properly, but when I delete T (equivalent ASCII value) I will get a segmentation fault.
#include<stdio.h>
#include<stdlib.h>
#define M 5
struct node{
int n; /* n < M No. of keys in node will always less than order of B
tree */
int keys[M-1]; /*array of keys*/
struct node *p[M]; /* (n+1 pointers will be in use) */
}*root=NULL;
enum KeyStatus { Duplicate,SearchFailure,Success,InsertIt,LessKeys };
void insert(int key);
void display(struct node *root,int);
void DelNode(int x);
void search(int x);
enum KeyStatus ins(struct node *r, int x, int* y, struct node** u);
int searchPos(int x,int *key_arr, int n);
enum KeyStatus del(struct node *r, int x);
int input_array[20]= {65,67,71,78,72,69,75,81,77,70,87,76,84,90,68,80,82,88,89,83};
int main()
{
int choice, i,key = 11;
printf("Creation of B tree for node %d\n",M);
while(1)
{
printf("1.Insert\n");
printf("2.Delete\n");
printf("3.Search\n");
printf("4.Display\n");
printf("5.Quit\n");
printf("Enter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1:
//printf("Enter the key : ");
//scanf("%d",&key);
//for(i=0;i<20;i++)
for(i=0;i<20;i++)
{
key = input_array[i];
insert(key);
}
//insert(key++);
//insert(key);
break;
case 2:
printf("Enter the key : ");
scanf("%d",&key);
DelNode(key);
break;
case 3:
printf("Enter the key : ");
scanf("%d",&key);
search(key);
break;
case 4:
printf("Btree is :\n");
display(root,0);
break;
case 5:
exit(1);
default:
printf("Wrong choice\n");
break;
}/*End of switch*/
}/*End of while*/
return 0;
}/*End of main()*/
void insert(int key)
{
struct node *newnode;
int upKey;
enum KeyStatus value;
value = ins(root, key, &upKey, &newnode);
if (value == Duplicate)
printf("Key already available\n");
if (value == InsertIt)
{
struct node *uproot = root;
root=malloc(sizeof(struct node));
root->n = 1;
root->keys[0] = upKey;
root->p[0] = uproot;
root->p[1] = newnode;
}/*End of if */
}/*End of insert()*/
enum KeyStatus ins(struct node *ptr, int key, int *upKey,struct node **newnode)
{
struct node *newPtr, *lastPtr;
int pos, i, n,splitPos;
int newKey, lastKey;
enum KeyStatus value;
if (ptr == NULL)
{
*newnode = NULL;
*upKey = key;
return InsertIt;
}
n = ptr->n;
pos = searchPos(key, ptr->keys, n);
if (pos < n && key == ptr->keys[pos])
return Duplicate;
value = ins(ptr->p[pos], key, &newKey, &newPtr);
if (value != InsertIt)
return value;
/*If keys in node is less than M-1 where M is order of B tree*/
if (n < M - 1)
{
pos = searchPos(newKey, ptr->keys, n);
/*Shifting the key and pointer right for inserting the new key*/
for (i=n; i>pos; i--)
{
ptr->keys[i] = ptr->keys[i-1];
ptr->p[i+1] = ptr->p[i];
}
/*Key is inserted at exact location*/
ptr->keys[pos] = newKey;
ptr->p[pos+1] = newPtr;
++ptr->n; /*incrementing the number of keys in node*/
return Success;
}/*End of if */
/*If keys in nodes are maximum and position of node to be inserted is
last*/
if (pos == M - 1)
{
lastKey = newKey;
lastPtr = newPtr;
}
else /*If keys in node are maximum and position of node to be inserted
is not last*/
{
lastKey = ptr->keys[M-2];
lastPtr = ptr->p[M-1];
for (i=M-2; i>pos; i--)
{
ptr->keys[i] = ptr->keys[i-1];
ptr->p[i+1] = ptr->p[i];
}
ptr->keys[pos] = newKey;
ptr->p[pos+1] = newPtr;
}
splitPos = (M - 1)/2;
(*upKey) = ptr->keys[splitPos];
(*newnode)=malloc(sizeof(struct node));/*Right node after split*/
ptr->n = splitPos; /*No. of keys for left splitted node*/
(*newnode)->n = M-1-splitPos;/*No. of keys for right splitted node*/
for (i=0; i < (*newnode)->n; i++)
{
(*newnode)->p[i] = ptr->p[i + splitPos + 1];
if(i < (*newnode)->n - 1)
(*newnode)->keys[i] = ptr->keys[i + splitPos + 1];
else
(*newnode)->keys[i] = lastKey;
}
(*newnode)->p[(*newnode)->n] = lastPtr;
return InsertIt;
}/*End of ins()*/
void display(struct node *ptr, int blanks)
{
if (ptr)
{
int i;
for(i=1;i<=blanks;i++)
printf(" ");
for (i=0; i < ptr->n; i++)
printf("%d ",ptr->keys[i]);
printf("\n");
for (i=0; i <= ptr->n; i++)
display(ptr->p[i], blanks+10);
}/*End of if*/
}/*End of display()*/
void search(int key)
{
int pos, i, n;
struct node *ptr = root;
printf("Search path:\n");
while (ptr)
{
n = ptr->n;
for (i=0; i < ptr->n; i++)
printf(" %d",ptr->keys[i]);
printf("\n");
pos = searchPos(key, ptr->keys, n);
if (pos < n && key == ptr->keys[pos])
{
printf("Key %d found in position %d of last dispalyednode\n",key,i);
return;
}
ptr = ptr->p[pos];
}
printf("Key %d is not available\n",key);
}/*End of search()*/
int searchPos(int key, int *key_arr, int n)
{
int pos=0;
while (pos < n && key > key_arr[pos])
pos++;
return pos;
}/*End of searchPos()*/
void DelNode(int key)
{
struct node *uproot;
enum KeyStatus value;
value = del(root,key);
switch (value)
{
case SearchFailure:
printf("Key %d is not available\n",key);
break;
case LessKeys:
uproot = root;
root = root->p[0];
free(uproot);
break;
}/*End of switch*/
}/*End of delnode()*/
enum KeyStatus del(struct node *ptr, int key)
{
int pos, i, pivot, n ,min;
int *key_arr;
enum KeyStatus value;
struct node **p,*lptr,*rptr;
if (ptr == NULL)
return SearchFailure;
/*Assigns values of node*/
n=ptr->n;
key_arr = ptr->keys;
p = ptr->p;
min = (M - 1)/2;/*Minimum number of keys*/
pos = searchPos(key, key_arr, n);
if (p[0] == NULL)
{
if (pos == n || key < key_arr[pos])
return SearchFailure;
/*Shift keys and pointers left*/
for (i=pos+1; i < n; i++)
{
key_arr[i-1] = key_arr[i];
p[i] = p[i+1];
}
return --ptr->n >= (ptr==root ? 1 : min) ? Success : LessKeys;
}/*End of if */
if (pos < n && key == key_arr[pos])
{
struct node *qp = p[pos], *qp1;
int nkey;
while(1)
{
nkey = qp->n;
qp1 = qp->p[nkey];
if (qp1 == NULL)
break;
qp = qp1;
}/*End of while*/
key_arr[pos] = qp->keys[nkey-1];
qp->keys[nkey - 1] = key;
}/*End of if */
value = del(p[pos], key);
if (value != LessKeys)
return value;
if (pos > 0 && p[pos-1]->n > min)
{
pivot = pos - 1; /*pivot for left and right node*/
lptr = p[pivot];
rptr = p[pos];
/*Assigns values for right node*/
rptr->p[rptr->n + 1] = rptr->p[rptr->n];
for (i=rptr->n; i>0; i--)
{
rptr->keys[i] = rptr->keys[i-1];
rptr->p[i] = rptr->p[i-1];
}
rptr->n++;
rptr->keys[0] = key_arr[pivot];
rptr->p[0] = lptr->p[lptr->n];
key_arr[pivot] = lptr->keys[--lptr->n];
return Success;
}/*End of if */
if (pos > min)
{
pivot = pos; /*pivot for left and right node*/
lptr = p[pivot];
rptr = p[pivot+1];
/*Assigns values for left node*/
lptr->keys[lptr->n] = key_arr[pivot];
lptr->p[lptr->n + 1] = rptr->p[0];
key_arr[pivot] = rptr->keys[0];
lptr->n++;
rptr->n--;
for (i=0; i < rptr->n; i++)
{
rptr->keys[i] = rptr->keys[i+1];
rptr->p[i] = rptr->p[i+1];
}/*End of for*/
rptr->p[rptr->n] = rptr->p[rptr->n + 1];
return Success;
}/*End of if */
if(pos == n)
pivot = pos-1;
else
pivot = pos;
lptr = p[pivot];
rptr = p[pivot+1];
/*merge right node with left node*/
lptr->keys[lptr->n] = key_arr[pivot];
lptr->p[lptr->n + 1] = rptr->p[0];
for (i=0; i < rptr->n; i++)
{
lptr->keys[lptr->n + 1 + i] = rptr->keys[i];
lptr->p[lptr->n + 2 + i] = rptr->p[i+1];
}
lptr->n = lptr->n + rptr->n +1;
free(rptr); /*Remove right node*/
for (i=pos+1; i < n; i++)
{
key_arr[i-1] = key_arr[i];
p[i] = p[i+1];
}
return --ptr->n >= (ptr == root ? 1 : min) ? Success : LessKeys;
}/*End of del()*/
What could be the problem?
Without knowing exactly how this should work I can say that you write outside of the p vector on
for (i=0; i < rptr->n; i++)
{
lptr->keys[lptr->n + 1 + i] = rptr->keys[i];
// When you delete key 84, rptr->n is 4 at one point which takes you outside
// p[M]
lptr->p[lptr->n + 2 + i] = rptr->p[i+1];
}
Valgrind is a good tool to use, and I found this problem by valgrind -v --leak-check=full <your executable>

segmentaion fault in deletion of node in B-tree [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Segmentation fault in btree implementation
I had already posted this question earlier asking for a help and i got some suggestion of how to debug, but still i am stuck in the same segmentation fault problem and not able to remove it please help me out, i have started c coding and i tried my best to debug it before posting it here again
Here M is the order of the tree, M = 5 means it can have 5 children and 4 keys,
1> press 1 it will insert keys automatically,( here i have input 20 numbers using a loop) so just press 1 data will be entered.
2 > Press 4 it will display.
3> Then go for delete option, if i try deleting either 71/84 it give an segmentation fault or throws memory map.
#include<stdio.h>
#include<stdlib.h>
#define M 5
struct node{
int n; /* n < M No. of keys in node will always less than order of B
tree */
int keys[M-1]; /*array of keys*/
struct node *p[M]; /* (n+1 pointers will be in use) */
}*root=NULL;
enum KeyStatus { Duplicate,SearchFailure,Success,InsertIt,LessKeys };
void insert(int key);
void display(struct node *root,int);
void DelNode(int x);
void search(int x);
enum KeyStatus ins(struct node *r, int x, int* y, struct node** u);
int searchPos(int x,int *key_arr, int n);
enum KeyStatus del(struct node *r, int x);
int input_array[20]= {65,67,71,78,72,69,75,81,77,70,87,76,84,90,68,80,82,88,89,83};
int main()
{
int choice, i,key;
printf("Creation of B tree for node %d\n",M);
while(1)
{
printf("1.Insert\n");
printf("2.Delete\n");
printf("3.Search\n");
printf("4.Display\n");
printf("5.Quit\n");
printf("Enter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1:
//printf("Enter the key : ");
//scanf("%d",&key);
for(i=0;i<20;i++)
{
key = input_array[i];
insert(key);
}
//insert(key++);
//insert(key);
break;
case 2:
printf("Enter the key : ");
scanf("%d",&key);
DelNode(key);
break;
case 3:
printf("Enter the key : ");
scanf("%d",&key);
search(key);
break;
case 4:
printf("Btree is :\n");
display(root,0);
break;
case 5:
exit(1);
default:
printf("Wrong choice\n");
break;
}/*End of switch*/
}/*End of while*/
return 0;
}/*End of main()*/
void insert(int key)
{
struct node *newnode;
int upKey;
enum KeyStatus value;
value = ins(root, key, &upKey, &newnode);
if (value == Duplicate)
printf("Key already available\n");
if (value == InsertIt)
{
struct node *uproot = root;
root=malloc(sizeof(struct node));
root->n = 1;
root->keys[0] = upKey;
root->p[0] = uproot;
root->p[1] = newnode;
}/*End of if */
}/*End of insert()*/
enum KeyStatus ins(struct node *ptr, int key, int *upKey,struct node **newnode)
{
struct node *newPtr, *lastPtr;
int pos, i, n,splitPos;
int newKey, lastKey;
enum KeyStatus value;
if (ptr == NULL)
{
*newnode = NULL;
*upKey = key;
return InsertIt;
}
n = ptr->n;
pos = searchPos(key, ptr->keys, n);
if (pos < n && key == ptr->keys[pos])
return Duplicate;
value = ins(ptr->p[pos], key, &newKey, &newPtr);
if (value != InsertIt)
return value;
/*If keys in node is less than M-1 where M is order of B tree*/
if (n < M - 1)
{
pos = searchPos(newKey, ptr->keys, n);
/*Shifting the key and pointer right for inserting the new key*/
for (i=n; i>pos; i--)
{
ptr->keys[i] = ptr->keys[i-1];
ptr->p[i+1] = ptr->p[i];
}
/*Key is inserted at exact location*/
ptr->keys[pos] = newKey;
ptr->p[pos+1] = newPtr;
++ptr->n; /*incrementing the number of keys in node*/
return Success;
}/*End of if */
/*If keys in nodes are maximum and position of node to be inserted is
last*/
if (pos == M - 1)
{
lastKey = newKey;
lastPtr = newPtr;
}
else /*If keys in node are maximum and position of node to be inserted
is not last*/
{
lastKey = ptr->keys[M-2];
lastPtr = ptr->p[M-1];
for (i=M-2; i>pos; i--)
{
ptr->keys[i] = ptr->keys[i-1];
ptr->p[i+1] = ptr->p[i];
}
ptr->keys[pos] = newKey;
ptr->p[pos+1] = newPtr;
}
splitPos = (M - 1)/2;
(*upKey) = ptr->keys[splitPos];
(*newnode)=malloc(sizeof(struct node));/*Right node after split*/
ptr->n = splitPos; /*No. of keys for left splitted node*/
(*newnode)->n = M-1-splitPos;/*No. of keys for right splitted node*/
for (i=0; i < (*newnode)->n; i++)
{
(*newnode)->p[i] = ptr->p[i + splitPos + 1];
if(i < (*newnode)->n - 1)
(*newnode)->keys[i] = ptr->keys[i + splitPos + 1];
else
(*newnode)->keys[i] = lastKey;
}
(*newnode)->p[(*newnode)->n] = lastPtr;
return InsertIt;
}/*End of ins()*/
void display(struct node *ptr, int blanks)
{
if (ptr)
{
int i;
for(i=1;i<=blanks;i++)
printf(" ");
for (i=0; i < ptr->n; i++)
printf("%d ",ptr->keys[i]);
printf("\n");
for (i=0; i <= ptr->n; i++)
display(ptr->p[i], blanks+10);
}/*End of if*/
}/*End of display()*/
void search(int key)
{
int pos, i, n;
struct node *ptr = root;
printf("Search path:\n");
while (ptr)
{
n = ptr->n;
for (i=0; i < ptr->n; i++)
printf(" %d",ptr->keys[i]);
printf("\n");
pos = searchPos(key, ptr->keys, n);
if (pos < n && key == ptr->keys[pos])
{
printf("Key %d found in position %d of last dispalyednode\n",key,i);
return;
}
ptr = ptr->p[pos];
}
printf("Key %d is not available\n",key);
}/*End of search()*/
int searchPos(int key, int *key_arr, int n)
{
int pos=0;
while (pos < n && key > key_arr[pos])
pos++;
return pos;
}/*End of searchPos()*/
void DelNode(int key)
{
struct node *uproot;
enum KeyStatus value;
value = del(root,key);
switch (value)
{
case SearchFailure:
printf("Key %d is not available\n",key);
break;
case LessKeys:
uproot = root;
root = root->p[0];
free(uproot);
break;
}/*End of switch*/
}/*End of delnode()*/
enum KeyStatus del(struct node *ptr, int key)
{
int pos, i, pivot, n ,min;
int *key_arr;
enum KeyStatus value;
struct node **p,*lptr,*rptr;
if (ptr == NULL)
return SearchFailure;
/*Assigns values of node*/
n=ptr->n;
key_arr = ptr->keys;
p = ptr->p;
min = (M - 1)/2;/*Minimum number of keys*/
pos = searchPos(key, key_arr, n);
if (p[0] == NULL)
{
if (pos == n || key < key_arr[pos])
return SearchFailure;
/*Shift keys and pointers left*/
for (i=pos+1; i < n; i++)
{
key_arr[i-1] = key_arr[i];
p[i] = p[i+1];
}
return --ptr->n >= (ptr==root ? 1 : min) ? Success : LessKeys;
}/*End of if */
if (pos < n && key == key_arr[pos])
{
struct node *qp = p[pos], *qp1;
int nkey;
while(1)
{
nkey = qp->n;
qp1 = qp->p[nkey];
if (qp1 == NULL)
break;
qp = qp1;
}/*End of while*/
key_arr[pos] = qp->keys[nkey-1];
qp->keys[nkey - 1] = key;
}/*End of if */
value = del(p[pos], key);
if (value != LessKeys)
return value;
if (pos > 0 && p[pos-1]->n > min)
{
pivot = pos - 1; /*pivot for left and right node*/
lptr = p[pivot];
rptr = p[pos];
/*Assigns values for right node*/
rptr->p[rptr->n + 1] = rptr->p[rptr->n];
for (i=rptr->n; i>0; i--)
{
rptr->keys[i] = rptr->keys[i-1];
rptr->p[i] = rptr->p[i-1];
}
rptr->n++;
rptr->keys[0] = key_arr[pivot];
rptr->p[0] = lptr->p[lptr->n];
key_arr[pivot] = lptr->keys[--lptr->n];
return Success;
}/*End of if */
if (pos > min)
{
pivot = pos; /*pivot for left and right node*/
lptr = p[pivot];
rptr = p[pivot+1];
/*Assigns values for left node*/
lptr->keys[lptr->n] = key_arr[pivot];
lptr->p[lptr->n + 1] = rptr->p[0];
key_arr[pivot] = rptr->keys[0];
lptr->n++;
rptr->n--;
for (i=0; i < rptr->n; i++)
{
rptr->keys[i] = rptr->keys[i+1];
rptr->p[i] = rptr->p[i+1];
}/*End of for*/
rptr->p[rptr->n] = rptr->p[rptr->n + 1];
return Success;
}/*End of if */
if(pos == n)
pivot = pos-1;
else
pivot = pos;
lptr = p[pivot];
rptr = p[pivot+1];
/*merge right node with left node*/
lptr->keys[lptr->n] = key_arr[pivot];
lptr->p[lptr->n + 1] = rptr->p[0];
for (i=0; i < rptr->n; i++)
{
lptr->keys[lptr->n + 1 + i] = rptr->keys[i];
lptr->p[lptr->n + 2 + i] = rptr->p[i+1];
}
lptr->n = lptr->n + rptr->n +1;
free(rptr); /*Remove right node*/
for (i=pos+1; i < n; i++)
{
key_arr[i-1] = key_arr[i];
p[i] = p[i+1];
}
return --ptr->n >= (ptr == root ? 1 : min) ? Success : LessKeys;
}/*End of del()*/
This is a lot to sift through, and this kind of stuff isn't easy (on purpose!)
Something that jumps out at me is this
if (p[0] == NULL)
{
if (pos == n || key < key_arr[pos])
return SearchFailure;
/*Shift keys and pointers left*/
for (i=pos+1; i < n; i++)
{
key_arr[i-1] = key_arr[i];
p[i] = p[i+1];
}
return --ptr->n >= (ptr==root ? 1 : min) ? Success : LessKeys;
}/*End of if */
What if p[1] is also null? All that will do is move p[1] into p[0]. Perhaps you need a function called "node reduce" or something that "moves the nodes to the front of the node?"
I found the error causing segmentation fault in this case by valgrind, and answered it in your other post. Please have a look at my answer.

Segmentation fault in btree implementation

Can anyone please help in removing this segmentation fault. I am working on this code for a week still unable to debug this. This code is a Btree implementation. The insertion part is working properly but there is an segmentation fault in deletion. I am unable to debug it, can anyone please help?
I have given the input based on this link (have converted alphabet value to ASCII value)
http://cis.stvincent.edu/html/tutorials/swd/btree/btree.html
When I delete the first H (equivalent ASCII value) it works properly, but when I delete T (equivalent ASCII value) I will get a segmentation fault.
#include<stdio.h>
#include<stdlib.h>
#define M 5
struct node{
int n; /* n < M No. of keys in node will always less than order of B
tree */
int keys[M-1]; /*array of keys*/
struct node *p[M]; /* (n+1 pointers will be in use) */
}*root=NULL;
enum KeyStatus { Duplicate,SearchFailure,Success,InsertIt,LessKeys };
void insert(int key);
void display(struct node *root,int);
void DelNode(int x);
void search(int x);
enum KeyStatus ins(struct node *r, int x, int* y, struct node** u);
int searchPos(int x,int *key_arr, int n);
enum KeyStatus del(struct node *r, int x);
int input_array[20]= {65,67,71,78,72,69,75,81,77,70,87,76,84,90,68,80,82,88,89,83};
int main()
{
int choice, i,key = 11;
printf("Creation of B tree for node %d\n",M);
while(1)
{
printf("1.Insert\n");
printf("2.Delete\n");
printf("3.Search\n");
printf("4.Display\n");
printf("5.Quit\n");
printf("Enter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1:
//printf("Enter the key : ");
//scanf("%d",&key);
//for(i=0;i<20;i++)
for(i=0;i<20;i++)
{
key = input_array[i];
insert(key);
}
//insert(key++);
//insert(key);
break;
case 2:
printf("Enter the key : ");
scanf("%d",&key);
DelNode(key);
break;
case 3:
printf("Enter the key : ");
scanf("%d",&key);
search(key);
break;
case 4:
printf("Btree is :\n");
display(root,0);
break;
case 5:
exit(1);
default:
printf("Wrong choice\n");
break;
}/*End of switch*/
}/*End of while*/
return 0;
}/*End of main()*/
void insert(int key)
{
struct node *newnode;
int upKey;
enum KeyStatus value;
value = ins(root, key, &upKey, &newnode);
if (value == Duplicate)
printf("Key already available\n");
if (value == InsertIt)
{
struct node *uproot = root;
root=malloc(sizeof(struct node));
root->n = 1;
root->keys[0] = upKey;
root->p[0] = uproot;
root->p[1] = newnode;
}/*End of if */
}/*End of insert()*/
enum KeyStatus ins(struct node *ptr, int key, int *upKey,struct node **newnode)
{
struct node *newPtr, *lastPtr;
int pos, i, n,splitPos;
int newKey, lastKey;
enum KeyStatus value;
if (ptr == NULL)
{
*newnode = NULL;
*upKey = key;
return InsertIt;
}
n = ptr->n;
pos = searchPos(key, ptr->keys, n);
if (pos < n && key == ptr->keys[pos])
return Duplicate;
value = ins(ptr->p[pos], key, &newKey, &newPtr);
if (value != InsertIt)
return value;
/*If keys in node is less than M-1 where M is order of B tree*/
if (n < M - 1)
{
pos = searchPos(newKey, ptr->keys, n);
/*Shifting the key and pointer right for inserting the new key*/
for (i=n; i>pos; i--)
{
ptr->keys[i] = ptr->keys[i-1];
ptr->p[i+1] = ptr->p[i];
}
/*Key is inserted at exact location*/
ptr->keys[pos] = newKey;
ptr->p[pos+1] = newPtr;
++ptr->n; /*incrementing the number of keys in node*/
return Success;
}/*End of if */
/*If keys in nodes are maximum and position of node to be inserted is
last*/
if (pos == M - 1)
{
lastKey = newKey;
lastPtr = newPtr;
}
else /*If keys in node are maximum and position of node to be inserted
is not last*/
{
lastKey = ptr->keys[M-2];
lastPtr = ptr->p[M-1];
for (i=M-2; i>pos; i--)
{
ptr->keys[i] = ptr->keys[i-1];
ptr->p[i+1] = ptr->p[i];
}
ptr->keys[pos] = newKey;
ptr->p[pos+1] = newPtr;
}
splitPos = (M - 1)/2;
(*upKey) = ptr->keys[splitPos];
(*newnode)=malloc(sizeof(struct node));/*Right node after split*/
ptr->n = splitPos; /*No. of keys for left splitted node*/
(*newnode)->n = M-1-splitPos;/*No. of keys for right splitted node*/
for (i=0; i < (*newnode)->n; i++)
{
(*newnode)->p[i] = ptr->p[i + splitPos + 1];
if(i < (*newnode)->n - 1)
(*newnode)->keys[i] = ptr->keys[i + splitPos + 1];
else
(*newnode)->keys[i] = lastKey;
}
(*newnode)->p[(*newnode)->n] = lastPtr;
return InsertIt;
}/*End of ins()*/
void display(struct node *ptr, int blanks)
{
if (ptr)
{
int i;
for(i=1;i<=blanks;i++)
printf(" ");
for (i=0; i < ptr->n; i++)
printf("%d ",ptr->keys[i]);
printf("\n");
for (i=0; i <= ptr->n; i++)
display(ptr->p[i], blanks+10);
}/*End of if*/
}/*End of display()*/
void search(int key)
{
int pos, i, n;
struct node *ptr = root;
printf("Search path:\n");
while (ptr)
{
n = ptr->n;
for (i=0; i < ptr->n; i++)
printf(" %d",ptr->keys[i]);
printf("\n");
pos = searchPos(key, ptr->keys, n);
if (pos < n && key == ptr->keys[pos])
{
printf("Key %d found in position %d of last dispalyednode\n",key,i);
return;
}
ptr = ptr->p[pos];
}
printf("Key %d is not available\n",key);
}/*End of search()*/
int searchPos(int key, int *key_arr, int n)
{
int pos=0;
while (pos < n && key > key_arr[pos])
pos++;
return pos;
}/*End of searchPos()*/
void DelNode(int key)
{
struct node *uproot;
enum KeyStatus value;
value = del(root,key);
switch (value)
{
case SearchFailure:
printf("Key %d is not available\n",key);
break;
case LessKeys:
uproot = root;
root = root->p[0];
free(uproot);
break;
}/*End of switch*/
}/*End of delnode()*/
enum KeyStatus del(struct node *ptr, int key)
{
int pos, i, pivot, n ,min;
int *key_arr;
enum KeyStatus value;
struct node **p,*lptr,*rptr;
if (ptr == NULL)
return SearchFailure;
/*Assigns values of node*/
n=ptr->n;
key_arr = ptr->keys;
p = ptr->p;
min = (M - 1)/2;/*Minimum number of keys*/
pos = searchPos(key, key_arr, n);
if (p[0] == NULL)
{
if (pos == n || key < key_arr[pos])
return SearchFailure;
/*Shift keys and pointers left*/
for (i=pos+1; i < n; i++)
{
key_arr[i-1] = key_arr[i];
p[i] = p[i+1];
}
return --ptr->n >= (ptr==root ? 1 : min) ? Success : LessKeys;
}/*End of if */
if (pos < n && key == key_arr[pos])
{
struct node *qp = p[pos], *qp1;
int nkey;
while(1)
{
nkey = qp->n;
qp1 = qp->p[nkey];
if (qp1 == NULL)
break;
qp = qp1;
}/*End of while*/
key_arr[pos] = qp->keys[nkey-1];
qp->keys[nkey - 1] = key;
}/*End of if */
value = del(p[pos], key);
if (value != LessKeys)
return value;
if (pos > 0 && p[pos-1]->n > min)
{
pivot = pos - 1; /*pivot for left and right node*/
lptr = p[pivot];
rptr = p[pos];
/*Assigns values for right node*/
rptr->p[rptr->n + 1] = rptr->p[rptr->n];
for (i=rptr->n; i>0; i--)
{
rptr->keys[i] = rptr->keys[i-1];
rptr->p[i] = rptr->p[i-1];
}
rptr->n++;
rptr->keys[0] = key_arr[pivot];
rptr->p[0] = lptr->p[lptr->n];
key_arr[pivot] = lptr->keys[--lptr->n];
return Success;
}/*End of if */
if (pos > min)
{
pivot = pos; /*pivot for left and right node*/
lptr = p[pivot];
rptr = p[pivot+1];
/*Assigns values for left node*/
lptr->keys[lptr->n] = key_arr[pivot];
lptr->p[lptr->n + 1] = rptr->p[0];
key_arr[pivot] = rptr->keys[0];
lptr->n++;
rptr->n--;
for (i=0; i < rptr->n; i++)
{
rptr->keys[i] = rptr->keys[i+1];
rptr->p[i] = rptr->p[i+1];
}/*End of for*/
rptr->p[rptr->n] = rptr->p[rptr->n + 1];
return Success;
}/*End of if */
if(pos == n)
pivot = pos-1;
else
pivot = pos;
lptr = p[pivot];
rptr = p[pivot+1];
/*merge right node with left node*/
lptr->keys[lptr->n] = key_arr[pivot];
lptr->p[lptr->n + 1] = rptr->p[0];
for (i=0; i < rptr->n; i++)
{
lptr->keys[lptr->n + 1 + i] = rptr->keys[i];
lptr->p[lptr->n + 2 + i] = rptr->p[i+1];
}
lptr->n = lptr->n + rptr->n +1;
free(rptr); /*Remove right node*/
for (i=pos+1; i < n; i++)
{
key_arr[i-1] = key_arr[i];
p[i] = p[i+1];
}
return --ptr->n >= (ptr == root ? 1 : min) ? Success : LessKeys;
}/*End of del()*/
What could be the problem?
Without knowing exactly how this should work I can say that you write outside of the p vector on
for (i=0; i < rptr->n; i++)
{
lptr->keys[lptr->n + 1 + i] = rptr->keys[i];
// When you delete key 84, rptr->n is 4 at one point which takes you outside
// p[M]
lptr->p[lptr->n + 2 + i] = rptr->p[i+1];
}
Valgrind is a good tool to use, and I found this problem by valgrind -v --leak-check=full <your executable>

Resources