How to get length of the longest prefix in Trie in C - c

I'm trying to figure out how to find the length of the longest prefix of two words in Trie. I was trying to find a solution, but I found nothing.
I already have an implementation of Trie, where the nodes are represent by structure:
struct node
{
int end; // 1 if node is end of word or 0 if not
int count; // The number of words that contain current node
struct node *letter[26]; // Array of nodes, which represent the alphabet
};
int length_of_longest_prefix(struct node *root)
{
//??????????
}
I tried to make a recursive function for this problem, but I could not do it.
Let´s think about this filled trie:
Filled trie
What is the best way to solve this problem?
Pseudocode will be very usefull.
My function:
//Global variable
int total_max;
//root = start
int length_of_longest_prefix(struct node *root, struct node *start)
{
int max = 0;
int depth = 0;
for (int i = 0; i < 26; i++)
{
if(root->letter[i] != NULL && root->letter[i]->count >= 2)
{
depth = length_of_longest_prefix(root->letter[i], start);
depth++;
if(root->letter[i] == start->letter[i])
{
depth = 0;
}
}
if(depth > total_max)
total_max = depth;
}
return depth;
}
int main(void)
{
total_max = 0;
struct node *root = (struct node*)malloc(sizeof(struct node));
for (int i = 0; i < 26; i++)
{
root->letter[i] = NULL;
}
root->end = 0;
root->count = 0;
/*Inserting strings to Trie*/
length_of_longest_prefix(root, root);
printf("%d\n", total_max);
return 0;
}

Related

How do implement Count sort using linked list?

What I am trying to do is to create a counting sort using a linked list so I can link two similar elements in the same index and then copy from left to right to the original array. But my Buckets[i] are always NULL even after insertion. So my resulting array does not change. I don't know what I am doing wrong.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
} **Buckets;
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int findMax(int A[], int n) {
int i, max = A[0];
for (i = 0; i < n; i++) {
if (A[i] > max)
max = A[i];
}
return max;
}
void Insert(struct Node *p, int x) {
while (p != NULL) {
p = p->next;
}
Node *t = t = (struct Node *)malloc(sizeof(struct Node));
t->data = x;
t->next = NULL;
p = t;
}
int Delete(struct Node *Buckets) {
while (Buckets->next != NULL) {
Buckets = Buckets->next;
}
int temp = Buckets->data;
free(Buckets);
return temp;
}
void BucketSort(int A[], int size) {
int max, i, j;
max = findMax(A, size);
Buckets = new Node * [max + 1];
for (i = 0; i < max + 1; i++) {
Buckets[i] = NULL;
}
for (i = 0; i < size; i++) {
Insert(Buckets[A[i]], A[i]); //insertion
}
i = j = 0;
while (i < max + 1) {
while (Buckets[i] != NULL) {
A[j++] = Delete(Buckets[i]); // copy back in array
}
i++;
}
}
int main() {
int arr[] = { 3, 8, 5, 1, 10 };
int size = sizeof(arr) / sizeof(arr[0]); //5
printf("\nBefore : ");
printArray(arr, size);
BucketSort(arr, size);
printf("\nAfter : ");
printArray(arr, size);
return 0;
}
Your Insert function doesn't really modify the list – you just assign the new node to a local variable, which goes out of scope immediately.
You can solve this by passing a pointer to a node pointer to the function. That pointer points at the head pointer at first and at the next member of the preceding node when you advance:
void Insert(struct Node **p, int x)
{
while (*p) p = &(*p)->next;
*p = new Node(x); // assume a c'tor here
}
Call the function like so:
for (i = 0; i < size; i++) {
Insert(&Buckets[A[i]] ,A[i]);
}
The same goes for deletion: You must modify the links or the list head when you delete:
int Delete(struct Node **p)
{
int temp = (*p)->data;
struct Node *del = *p;
*p = (*p)->next;
delete del;
return temp;
}
(This code extracts the head node, which is probably what you want: You insert at the end, then retrieve from the beginning. That should preserve the original order. Not that it matters miuch in your case, where you have no data beside the int.)
Call Delete like so:
i = j = 0;
while (i < max + 1) {
while (Buckets[i]) {
A[j++] = Delete(&Buckets[i]);
}
i++;
}

trying to print a array of structs in C

I was asked to build a function that's receive a static two dimensional array with a lot of zeroes and turn it to an array of structs. each struct contains the value which is not zero and the index of the column.
Now I have built it but the problem is with the print function.
1) When I try to print twice it only prints one time and the second time list becomes NULL. Why does this occur?
print(list);
print(list);
2) Why can't I print like I did in the main function?
printf("this is just a print |%d||%d| ", list[0]->next->next->next->data, list[0]->col);
Why I don't have access to it, the program crashes...
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//#include <vld.h>
#include <string.h>
#include <ctype.h>
#define C 5
#define N 4
typedef struct Node {
int data;
int col;
struct Node *next;
} node;
node **fun(int arr[N][C]) {
int i, j, k;
node **list;
node *temp;
list = (node**)calloc(N, sizeof(node *));
for (i = 0; i < N; i++) {
list[i] = NULL;
for (j = C - 1; j >= 0; j--)
if (arr[i][j] != 0) {
temp = (node*)malloc(sizeof(node));
temp->data = arr[i][j];
temp->col = j;
temp->next = list[i];
list[i] = temp;
}
}
return list;
}
void print(node **head) {
int i;
node **temp = head;
for (i = 0; i < N; i++) {
while (temp[i]) {
printf("|%d||%d| ", temp[i]->data, temp[i]->col);
temp[i] = temp[i]->next;
}
printf("\n\n");
}
}
void main() {
int arr[N][C] = { {0,0,4,0,7}, {3,0,0,0,0}, {9,1,0,6,0} , {0,0,0,0,0} };
node **list;
list = fun(arr);
print(list); ///////////
print(list); ///////////////
printf("this is just a print |%d||%d| ", list[0]->next->next->next->data, list[0]->col);
}
As was mentioned in the comments, you are destroying your list of pointer in the process of printing them:
while(temp[i])
{ printf("|%d||%d| ",temp[i]->data,temp[i]->col);
temp[i]=temp[i]->next; // <---- here
}
Each temp[i] is the same as head[i], so you modify the original list as you do this. The while loop exits when this value is NULL, so the end result is that all array elements are NULL.
You need to assign this value to a temporary so you can walk the list without changing it:
node *temp2 = temp[i];
while(temp2)
{ printf("|%d||%d| ",temp2->data,temp2->col);
temp2=temp2->next;
}
Your print function modifies the array: it uses the array elements to iterate through the lists, and leaves them with a NULL value.
Here is a corrected version:
void print(node **head) {
int i;
for (i = 0; i < N; i++) {
node *temp;
for (temp = head[i]; temp; temp = temp->next) {
printf("|%d||%d| ", temp->data, temp->col);
}
printf("\n\n");
}
}

When I add an element to a linked list contained in an array of linked lists why every other element of the list gets deleted?

UPDATED
The problem of this code is that after the matrix has been transformed into an array of linked lists, it looks like no value is contained in the array of linked lists.
I think the problem is in the function that add a node to a specific list of the array of linked lists.
// node
struct node {
int n;
struct node* next_ptr;
};
// prototypes
void fill_mat(int mat[][SIZE]);
void mat_to_list(int mat[][SIZE]);
void insertSortedLinkedList(struct node *l, int value);
void print_mat(int mat[][SIZE]);
void print_vet();
// array of pointers
struct node* vet[SIZE];
int visitato[SIZE];
// main function
int main(int argc, const char *argv[]) {
int mat[SIZE][SIZE];
int i, j;
// reset the matrix
for(i = 0; i < SIZE; ++i) {
for(j = 0; j < SIZE; ++j) {
mat[i][j] = 0;
}
}
// generate graph with weights
srand(time(NULL));
fill_mat(mat);
// transform matrix in an array of linked lists
mat_to_list(mat);
print_mat(mat);
printf("\n");
print_vet();
return 0;
}
// generate graph
void fill_mat(int mat[][SIZE]) {
int x, y, z;
for(x = 0; x < (SIZE * SIZE) / 2;) {
y = rand() % SIZE;
z = rand() % SIZE;
if(mat[y][z] == 0) {
mat[y][z] = rand() % 10 + 1;
++x;
}
}
}
// insert in list
void addNode(struct node **st, int d) {
struct node *temp = *st;
if(temp == NULL) {
temp = malloc(sizeof(struct node));
} else {
while((temp)->next_ptr != NULL) {
temp = temp->next_ptr;
}
temp->next_ptr = malloc(sizeof(struct node));
temp = temp->next_ptr;
}
temp->n = d; // this must done using strncpy
temp->next_ptr = NULL;
}
// transform matrix to array of linked lists
void mat_to_list(int mat[][SIZE]) {
int i, j;
// reset array
for(i = 0; i < SIZE; ++i) {
vet[i] = NULL;
}
for(i = 0; i < SIZE; ++i) {
for(j = 0; j < SIZE; ++j) {
if(mat[i][j] != 0) {
addNode(&(vet[i]), mat[i][j]);
}
}
}
}
// print matrix
void print_mat(int mat[][SIZE]) {
int i, j
;
for(i = 0; i < SIZE; ++i) {
for(j = 0; j < SIZE; ++j) {
printf("%-2d ", mat[i][j]);
}
printf("\n");
}
}
// print array of linked lists
void print_vet() {
int i;
struct node* temp;
for(i = 0; i < SIZE; ++i) {
printf("ARRAY CELL: %d\n", i);
temp = vet[i];
while(temp != NULL) {
printf("NODE VALUE --> ");
printf("%d\n", temp->n);
temp = temp->next_ptr;
}
printf("\n");
}
}
I have not understood where there is an array of lists and how long you are going to show your editions of the function. But in any case a correct function can look the following way
void addNode( struct node **st, int d )
{
while ( *st ) st = &( *st )->next_ptr;
*st = malloc( sizeof( struct node ) );
( *st )->n = d;
( *st )->next_ptr = NULL;
}
Or the following way
int addNode( struct node **st, int d )
{
while ( *st ) st = &( *st )->next_ptr;
*st = malloc( sizeof( struct node ) );
int success = *st != NULL;
if ( success )
{
( *st )->n = d;
( *st )->next_ptr = NULL;
}
return success;
}
It looks like you are modifying the original pointer.
An iterator can be used to find the last node.
In your calling function, you can create an iterator.
first = (node *) malloc(sizeof(node));
iterator = first;
In your function, you can pass the iterator
void addNode(node *iterator, int d) {
/*Create a new node*/
newNode = (node *) malloc(sizeof(node));
newNode->n = d;
newNode->next_ptr = NULL;
/*Iterate through your list to find end*/
if (iterator != 0) {
while (iterator->next != 0) {
iterator = iterator->next;
}
}
/*Add item to last link in list*/
iterator->next = newNode;
}

Access violation reading location 0xCDCDCDCD

As the title states, I'm getting an error
Access violation reading location 0xCDCDCDCD.
Now I'm dealing with an array of linked lists, and I believe the trouble to be something around adding to the linked list. I'm fine with this usually, but I feel I'm doing something wrong with memory allocation.
Here are my structs:
Graph:
typedef struct graph
{
int V;
int *state;
EdgeList *edges;
} Graph;
Edge:
typedef struct edge
{
int toVertex;
int weight;
} Edge;
EdgeList:
typedef struct edgeNode
{
Edge edge;
struct edgeNode *next;
} *EdgeList;
Here is the main function that runs it all:
main()
{
Graph myGraph;
scanf("%d", &(myGraph.V));
myGraph.state = (int)malloc(myGraph.V*sizeof(int));
myGraph.edges = (EdgeList*)malloc(myGraph.V*sizeof(EdgeList));
int *inDegrees;
inDegrees = (int)malloc(sizeof(int)*myGraph.V);
/* Sets all array values to 0 */
for (int counter = 0; counter < myGraph.V; counter++)
{
inDegrees[counter] = 0;
}
for (int i = 0; i < myGraph.V; i++)
{
int number_of_edges;
int input = 0; /*For that little experimental bit*/
scanf("%d", &(myGraph.state[i]));
scanf("%d", &number_of_edges);
if (number_of_edges > 0)
{
for (int j = 0; j < number_of_edges; j++)
{
Edge newEdge;
scanf("%d,%d", &(newEdge.toVertex), &(newEdge.weight));
inDegrees[newEdge.toVertex]++;
printf("%s%d\n", "\nOoh, new input for ", newEdge.toVertex);
/*insert at front*/
EdgeList newNode = (EdgeList)malloc(sizeof (struct edgeNode));
newNode->edge = newEdge;
newNode->next = myGraph.edges[i];
myGraph.edges[i] = newNode;
/* Bit to calculate state.*/
EdgeList current = myGraph.edges[i];
while (current != NULL)
{
if (current->edge.toVertex == i)
{
input += (current->edge.weight)*(myGraph.state[i]);
}
current = current->next;
}
}
if (input > 0)
{
myGraph.state[i] = 1;
}
else
{
myGraph.state[i] = 0;
}
}
}
//print
for (int k = 0; k < myGraph.V; k++)
{
printf("\n%s%d%s", "In degrees for ", k, ": ");
printf("%d", inDegrees[k]);
}
}
In particular, the error comes during the traversal of the linked list. It's in the above code, but I'll highlight it here:
EdgeList current = myGraph.edges[i];
while (current != NULL)
{
if (current->edge.toVertex == i)
{
input += (current->edge.weight)*(myGraph.state[i]);
}
current = current->next;
}
If anyone can help, it'd be greatly appreciated because I'm rather stuck.
An value in uninitialized buffer allocated via malloc() is assigned to newNode->edge in newNode->next = myGraph.edges[i];.
The newNode is set to current via myGraph.edges[i] = newNode; and EdgeList current = myGraph.edges[i];.
Assuming that malloc() succeeded, current isn't NULL here, so it is entering the loop.
The uninitialized value assinged in 1 is assigned to current in current = current->next;.
An undefined behavior is invoked by using value in buffer allocated via malloc() and uninitialized at current != NULL.
To fix this error, initialize myGraph.edges in, for example, this way:
myGraph.edges = (EdgeList*)malloc(myGraph.V*sizeof(EdgeList));
for (int i = 0; i < myGraph.V; i++)
{
myGraph.edges[i] = NULL;
}
Also, remove the harmful casts to int of the pointer returned from malloc(). Casting the return values to pointers explicitly is also not considered as good.

Find sum of shortest root to leaf path in a binary tree

I am trying to implement a function which will return the sum of the shortest path in a binary tree. I am getting the incorrect answer of 8 instead of 4 for the following tree.
1
/ \
2 3
/ \
4 5
int sumOfShortestPath(BinaryTreeNode *root, std::vector<int> vec) {
if(!root) return 0;
static int minPathLength = INT_MAX;
static int pathLength = 0;
static int sum = 0;
vec.push_back(root -> data);
pathLength++;
if(root -> left == NULL and root -> right == NULL) {
if(pathLength < minPathLength){
minPathLength = pathLength;
sum = sum_vector(vec);
pathLength = 0;
}
}
sumOfShortestPath(root -> left, vec);
sumOfShortestPath(root -> right, vec);
return sum;
}
I believe my logic is correct but i'm unsure where i'm going wrong. Basically, if I encounter a smaller path, I update minPathLength and sum and reset pathLength back to 0 for the next path exploration.
You're kind of on the right track, but I think the static variables are tripping you up some here. Also, I don't see a reason to keep a list of the values. You only need just enough information to determine if the left or right branches are the shortest.
Here's my revised version:
#include <stdio.h>
class node
{
public:
node *left, *right;
int value;
node (int v) : left(nullptr), right(nullptr), value(v) { }
};
int sumOfShortestPath(node *root, int *cnt)
{
if (!root)
{
*cnt = 0;
return 0;
}
int lcnt;
int rcnt;
int lsum = sumOfShortestPath(root->left, &lcnt);
int rsum = sumOfShortestPath(root->right, &rcnt);
if (lcnt < rcnt)
{
*cnt = lcnt + 1;
return root->value + lsum;
}
else
{
*cnt = rcnt + 1;
return root->value + rsum;
}
}
node *buildTree()
{
node *root = new node(1);
root->right = new node(3);
root->left = new node(2);
root->left->left = new node(4);
root->left->right = new node(5);
return root;
}
void main(void)
{
node *tree = buildTree();
int work = 0;
int val = sumOfShortestPath(tree, &work);
printf("Result: %d\r\n", val);
}
There are probably much more optimal ways of counting tree lengths than this, but this gets the job done at the end of the day.

Resources