how can i develop a program which reads words from a text file and creates an alphabetically sorted binary search tree using those words? here is my code
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct treeNode {
char data[20];
int count;
struct treeNode *leftPtr, *rightPtr;
};
int number;
typedef struct treeNode TreeNode;
typedef TreeNode *TreeNodePtr;
void insertNode (TreeNodePtr *treePtr,char word[]);
void alphabetic(TreeNodePtr treePtr);
int main(){
/*reading strings from the file and add them to the tree*/
char first[20];
FILE *fp1;
TreeNodePtr rootPtr=NULL;
int c;
fp1=fopen("output.txt","r");
do{
c=fscanf(fp1,"%s",first);
insertNode(&rootPtr,first);
}while(c!=EOF);
fclose(fp1);
alphabetic(rootPtr);
system("PAUSE");
}
/*for adding nodes to tree*/
void insertNode (TreeNodePtr *treePtr,char word[20]){
TreeNode *temp = NULL;
if(*treePtr == NULL)
{
temp = (TreeNode *)malloc(sizeof(TreeNode));
temp->leftPtr = NULL;
temp->rightPtr = NULL;
temp->data[20] = word[20];
*treePtr = temp;
}
else if(strcmp(word,(*treePtr)->data)<0){
insertNode(&((*treePtr)->leftPtr),word);
}
else if (strcmp(word,(*treePtr)->data)>0){
insertNode(&((*treePtr)->rightPtr),word);
}
else{
number++;
}
}
/*for sorting alphabetically*/
void alphabetic(TreeNodePtr treePtr){
if(treePtr!=NULL){
alphabetic(treePtr->leftPtr);
printf("%3d\n",treePtr->leftPtr);
alphabetic(treePtr->rightPtr);
}
}
when i have a .txt including 4 words my program writes onli four 0' s as output.
This line is wrong:
temp->data[20] = word[20];
It copies a single character from one invalid location to another.
Change it to:
strcpy(temp->data, word);
since you want to copy a string.
Also this line looks wrong:
printf("%3d\n",treePtr->leftPtr);
I'm guessing you want to print the contents of the data string here, so it should be:
printf("%s\n", treePtr->data);
or if you want the integer count element it would be:
printf("%d\n", treePtr->count);
Related
I've implemented a dictionnary in C using tree, this tree stores a word and its definition as followed:
As you can see, some words are sharing same letters.
But now i'd like to implement a delete function but don't know how to proceed ... I know that I should begin to delete the end of the word ...
Here is my code, thank you for your future help !
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _noeud{
char *value;
struct _noeud *child[26];
}noeud_t;
typedef struct tree{
node_t root;
}Tree;
Tree dict;
int getPos(char letter){
char alpha[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int i;
for(i=0;i<strlen(alpha);i++){
if(alpha[i]==letter){
return i;
}
}
return -1;
}
void addWord(node_t *node, char *word, char *def){
int i;
for(i = 0; i < strlen(word);i++){
int letter=getPos(word[i]);
if(letter==-1){
printf("Unknown letter... \n");
}
node_t *parent = node;
node = node->child[letter];
if(!node){
node = malloc(sizeof(node_t));
parent->child[letter]=node;
}
}
node->value = malloc(strlen(def)+1);
strncpy(node->value,def,strlen(def)),
printf("Word %s added to dictionnary.\n",word);
fflush(stdin);
}
void findWord(node_t *node, char *word){
printf("Looking for word %s \n",word);
int i;
for(i=0;i<strlen(word);i++) {
int letter = getPos(word[i]);
if(NULL ==node->child[letter]){
printf("Unknown word ...\n");
return;
}
else{
node = node->child[letter];
}
}
printf("Word found, its definition is : %s\n",node->value);
}
void deleteWord(node_t *node, char *word){
int i=0;
for(i=0;i<strlen(word);i++) {
//...
}
printf("Word deleted !\n");
}
int main(){
addWord(&dico.root,"dog","it's an animal");
addWord(&dico.root,"pineapple","it's a fruit");
addWord(&dico.root,"car","something to drive");
findWord(&dico.root,"dog");
findWord(&dico.root,"car");
findWord(&dico.root,"pineapple");
deleteWord(&dico.root,"pineapple");
return 0;
}
I can give you an idea on how to solve it, but sorry I didn’t write the code.
So from your code, I can see that you have findWord function, if that works perfectly then use it inside your delete go find the word at this stage you’re pointing to it now you have to think of three possibilities.
If the word that will be deleted doesn’t have any child then delete it with no more complication.
If the word that will be deleted has a single child then make the parent of the word point to the word’s child.
If the word that will be deleted has more than one child then replace the word with one of the children and then delete it.
I hope this will help you
I'm trying to insert into my BST but I'm struggling with creating a loop out of it.
The code works when I insert one by one, but when I try to put it into a loop it doesn't insert correctly.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> // for strcmp()
#include <ctype.h> // for toupper()
typedef struct BstNode{
//char name[20];
// int data;
struct BstNode* left;
struct BstNode* right;
char* name;
}BstNode;
typedef int (*Compare)(const char*, const char*); // makes comparisons easier
/* Returns pointer address to newly created node */
BstNode* createNode(char* name){
BstNode* newNode = (BstNode*)malloc(sizeof(BstNode)); // Allocates memory for the newNode
newNode->name = name; // newNode->data is like newNode.data
newNode->left= NULL;
newNode->right = NULL;
return newNode;
}
//insert node into Tree recursively
BstNode* insertNode(BstNode* node, char* name, Compare cmp){
int i;
/* char *s1 = node->name;
char *s2 = name;
printf("s1: %s, s2: %s\n", s1,s2);
i = strcmp(s1, s2); // if =1, s1 is greater
printf("i: %d\n", i); */
if(node == NULL){// if tree is empty
// printf("inside NULL\n");
node = createNode(name);
//return node;
}
else{
i = cmp (name, node->name); // sweet
if(i == -1){
// printf("inside left\n");
node->left = insertNode(node->left, name, cmp);
//return node;
}
else if(i == 1){
// printf("inside right\n");
node->right = insertNode(node->right, name, cmp);
//return node;
}
else if(i == 0 ){ //avoid duplicates for now
// printf("inside 0\n");
printf("Name is in BST\n");
return NULL;
}
}
return node;
}
BstNode* printTree(BstNode* node){
if(node == NULL){
return NULL;
}
printTree(node->left);
printf("%s\n",node->name);
printTree(node->right);
}
int CmpStr(const char* a, const char* b){
return (strcmp (a, b)); // string comparison instead of pointer comparison
}
//void Insert(Person *root, char name[20]);
int main(){
BstNode* root = NULL; // pointer to the root of the tree
char buf[100];
char option = 'a';
while(1) {
printf("Enter employee name");
scanf("%s",buf);
printf ("Inserting %s\n", buf);
root = insertNode(root, buf, (Compare)CmpStr);
printTree(root);
}
}
I can do root = insertNode(root, name, (Compare)CmpStr)
several times in code, but if I try to loop it with user input it won't insert correctly. I'm not sure if it has to do with the fact that I'm using scanf() or root not being set correctly. I've tried using fgets() as well but I'm not too sure how to use it and keep messing that up.
Any help is appreciated.
In your loop, you always pass the same buffer to your insert function; Your createNode does not copy the content of the buffer but rather stores a reference to the (always) same buffer; Hence, changing the buffer content after insert will also change the "content" of previously inserted nodes.
I'd suggest to replace newNode->name = name in createNode with newNode->name = strdup(name). This will actually copy the passed "contents" and gives your BST control over the memory to be kept. Thereby don't forget to free this memory when deleting nodes later on.
I am trying to read characters into a linked list (I made this simple test code just to try to read in the characters) for some reason I cannot get it to read in a character value.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
char name[50];
struct node *next;
}*head;
void add(char AddName);
int main()
{
head = NULL;
char TempName[50];
printf("What Name");
scanf(" %s", TempName);
add(TempName);
printf("%s",head->name);
return 0;
}
void add(char AddName)
{
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
strcpy(temp->name,AddName);
head = temp;
head->next = NULL;
}
I understand this is not how a linked list works I just made this to try to get to be able to run a single character name into the struct and print it back out. (I should be able to enter in the name Bob and it prints bob)
I think your function parameter definition is wrong. Try this:
void add(char *AddName)
{
....
}
I'm working in C and am having some trouble. I need to store an array of chars (string) across a linked list. In other words, convert a string to a linked list. Basically, one character per node. For example string, dog\0, rather then storing a null character in the last node it would just point to a null pointer to signify the end of the string…… d->o->g->NULL
An suggestions would be great, thank you
int main(){
char *string;
string = malloc(sizeof(char)*100);
strcpy(string,"cheese");
node *list = NULL;
list = createNode(string[0]);
int i;
for(i=1;i<strlen(string);i++){
// this is where I'm stuck, the first char 'c'is in,
// I'm guessing i wanna loop through and
// store each char in a new node ?
}
return 0;
}
node *createNode(char data){
node *ptr = malloc(sizeof(node));
if (ptr == NULL)
{
return NULL;
}
ptr->data = data;
ptr->next = NULL;
return ptr;
}
Here is how to do this in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
node *next;
char data;
};
node *createNode(char data, node *parent) {
node *ptr=(node*)malloc(sizeof(node));
if(ptr==NULL) {
fprintf(stderr, "Memory allocation error.\n");
exit(1);
}
if(parent!=NULL) parent->next=ptr;
ptr->data=data;
ptr->next=NULL;
return ptr;
}
int main() {
char str[]="cheese";
// Store the string to the list
node *first=NULL, *cur=NULL;
for(int i=0, len=strlen(str); i<len; i++) {
cur=createNode(str[i],cur);
if(first==NULL) first=cur;
}
// Now print it out
cur=first;
while(cur!=NULL) {
printf("%c\n", cur->data);
cur=cur->next;
}
_getwch();
return 0;
}
If C++ is OK then here is a working sample:
#include <iostream>
#include <list>
using namespace std;
int main() {
char str[]="cheese", chr;
// Store the string in the list
std::list<char> clist;
for (int i=0, len=strlen(str); i<len; i++)
clist.push_back(str[i]);
clist.push_back('\0');
// Display the list
do {
chr=clist.front();
cout<<chr<<endl;
clist.pop_front();
} while(chr);
_getwch();
return 0;
}
Basically I have to store words in linked list with each character having its own node. I get really confused with nested structures. How do I go to the next node? I know i'm doing this completely wrong which is why I'm asking.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
char letter;
}NODE;
typedef struct handle
{
NODE **arr;
}HANDLE;
HANDLE * create();
void insert(handle **, char, int);
int main(int argc, char **argv)
{
FILE *myFile;
HANDLE *table = (HANDLE *)malloc(sizeof(HANDLE));
NODE *linked = (NODE *)malloc(sizeof(NODE));
int counter = 0;
linked = NULL;
table->arr[0] = linked;
char c;
myFile = fopen(argv[argc], "r");
while((c = fgetc(myFile)) != EOF)
{
if(c != '\n')
insert(&table, c, counter);
else
{
counter++;
continue;
}
}
}
void insert(HANDLE **table, char c, int x)
{
(*table)->arr[x]->letter = c; //confused on what to do after this or if this
//is even correct...
}
You have a linked list of words with each word being a linked list of characters. Am I right? If so, it is better to use the names for what they are:
typedef struct char_list
{
char letter;
struct char_list * next;
} word_t;
typedef struct word_list
{
word_t * word;
struct word_list_t * next;
} word_list_t;
Now, you can populate the lists as per need.
For a linked-list, you typically have a link to the next node in the node structure itself.
typedef struct node
{
char letter;
struct node *next;
}NODE;
Then from any given node NODE *n, the next node is n->next (if not NULL).
insert should scan the list until it finds an n->next that is NULL, and allocate a new node at the end (make sure to set its next to NULL).
You may want to have a function to initialize a new list given the table index, and a separate function to initialize a new node.