Hello, I am studying for my final exam, so from my previous exam, I
got partial credit for this problem. recursive algorithm such that it
counts how many nodes of a given linked list have info values less
than the given threshold value
typedef struct LLNode {
int info;
struct LLNode* pNext;
}LLNode;
int recCount(LLNode *front, int threshold)
{
}
my answer was
int count = 0;
int total_less;
if(front == NULL)
return 0 ;
if(count < threshold)
count = 1 + recCount(front->next, front->info);
total_less++;
return total_
Shorter version:
If value is smaller, add +1 to result and check the next node in the list, else just check for next node without adding to count.
int recCount(struct NODE *N, int value)
{
if(N == NULL)
return 0;
if(N->data < value)
return 1 + recCount(N->next, value);
return recCount(N->next, value);
}
Example code:
http://tpcg.io/36qFkO
I'm afraid that you are not sending threshold to recursive calls.
recCount(front->next, front->info);
And I'm not sure why below condition is supposed to be there.
if(count < threshold) //as count is initialized to 0.
Example of recursive:
int recCount(LLNode *front, int threshold)
{
int count = 0;
if(front == NULL)
return 0 ;
if (front->info < threshold)
count++;
count = count + recCount(front->next, threshold);
return count;
}
Related
I am writing a recursive function to find if there is a path from the root to a leaf that sums up to a certain number or not (user inputs the sum). Each time I move forward into a new recursive call, I increment the value of current_sum with the value of node->data. Current_sum is declared/initialized outside of the function. So this works fine to get the sum to the left-ermost leaf. However after that, the current_sum just keeps increasing, as I don't have an appropriate decrement operation to go with it. So if there does exist a path that adds up to a certain number in the righter branches, for example: 1 2 # # 3 # #, and I check for path sum = 4, (1+3), it would not get that. (If i check for sum=3 (1+2), it does get it.)
So I am looking for the correct place in my code to put the decrement operation. I was thinking something like: current_sum -= root->data. However I've tried putting it a lot of different places, but all of them seem to be wrong places. Either they disrupt the original tracker to get to even the very first leftermost leaf. Or they don't decrement at all (if I put it after the both the left/right recursive calls). I also do need it to keep decrementing while it goes UP but increment while it goes DOWN. Is there a way to write this in code, I am curious? Or, is this just a bad algorithm/approach?
I've seen other ways of solving this problem, such as https://www.geeksforgeeks.org/root-to-leaf-path-sum-equal-to-a-given-number/, which seem really nice, I just wanted to know if there was a way to resolve the one I started.
int current_sum = 0;
int sumPath(Node * root, int sum)
{
if (root == NULL)
{
return 0;
}
current_sum += root->data;
if ((root->left == NULL) && (root->right == NULL))
{
if (current_sum == sum)
{
return 1;
}
else
{
return 0;
}
}
int the_left = sumPath(root->left, sum);
int the_right = sumPath(root->right, sum);
////////////////////current_sum -= root->data; (?)
if (the_left>0)
{
return the_left;
}
else if (the_right>0)
{
return the_right;
}
return 0;
}
You may get invalid output, because of not sending current_sum as a parameter. Because current_sum needs to be updated for a particular stack-trace or function call, not for commonly for all the function calls. and this may give you an invalid state.
UPDATE
int isPossible(Node * root, int currentSum, int sum) {
if(!root) return 0;
currentSum += root.node;
// when you find the sum, and can't move further down
if(sum == currentSum && root->left == null && root->right == null) return 1;
int flag = 0;
// going down on left side
flag = isPossible(root->left, currentSum, sum);
// needs to check right side, only when you couldn't find sum on left
if(!flag)
flag = isPossible(root->right, currentSum, sum);
// return the state
return flag;
}
your code is fine, u just need to pass sum - current_sum in the recursive call. This is your code with some hinted modifications.
#include <stdio.h>
// remove global current_sum
struct Node {
char* name;
int data;
struct Node* left;
struct Node* right;
};
int sumPath(struct Node* root, int sum) {
if (root == NULL) {
return 0;
}
if ((root->left == NULL) && (root->right == NULL)) {
if (current_sum == sum) {
printf("%s ", root->name); // if the branch matches, print name
return 1;
} else {
return 0;
}
}
int the_left = sumPath(root->left, sum - root->data); // pass the subtracted sum
int the_right = sumPath(root->right, sum - root->data); // pass the subtracted sum
if (the_left > 0) {
printf("%s ", root->name); // if the branch matches, print name
return the_left;
} else if (the_right > 0) {
printf("%s ", root->name); // if the branch matches, print name
return the_right;
}
return 0;
}
int main() {
struct Node n1 = {.data = 1, .name = "n1"}; // n1
struct Node n2 = {.data = 1, .name = "n2"}; // ___|___
struct Node n3 = {.data = 1, .name = "n3"}; // | |
struct Node n4 = {.data = 1, .name = "n4"}; // n2 n4
// ___|
n1.left = &n2; // |
n1.right = &n4; // n3
n2.left = &n3; //
sumPath(&n1, 3); // no. of steps including the root
return 0;
}
// output
// n3 n2 n1
I'm writing a lab assignment for programming classes. I need to do it in C :). The task I choose looks as follows: I created three kinds of data types in C: linked list, binary tree and avl tree. All the data handle 5,000,000 elements. I need to measure how long it takes to find and not find element in certain step. I have fixed values for positive and negative findings.
Here is some of my code that contains function for creating array of 5,000,000 numbers and two function for binary tree adding and finding node. I hope that the code is quite clear.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5000000
typedef struct Node {
int data;
struct Node *left, *right;
} Node;
void evenArrayGen(int num, int even_nums[]);
void shuffle(int numbers[]);
void addNode(Node **root, int value);
Node* findNode(Node *root, int value);
/** Recursively adds given value to the tree
*
* #param root
* #param value
*
*/
void addNode(Node **root, int value) {
Node *temp;
///check statement to avoid infinite loop in adding
if(*root == NULL) {
temp = (Node*)malloc(sizeof(Node));
temp->data = value;
temp->left = temp->right = NULL;
*root = temp;
return;
}
///recursively check where to add node
///if smaller than the root add to the left
///if bigger than the root add to the right
else {
temp = *root;
if(value < temp->data) {
addNode(&(temp->left), value);
} else {
addNode(&(temp->right), value);
}
return;
}
}
/** Recursively searches for Node with given value
*
* #param root
* #param value
* #return Node or NULL (if Node was not found)
*
*/
Node* findNode(Node *root, int value) {
Node *temp;
///check statement to avoid infinite loop in searching
///if it reachese that point given value is not in the tree
if(root == NULL) {
// printf("Given value is not in the tree\n");
return NULL;
}
temp = root;
if(temp->data == value) {
// printf("Searched value is: %i\n", temp->data);
return temp;
} else if(value < temp->data) {
findNode(temp->left, value);
} else {
findNode(temp->right, value);
}
}
/** Generates array of ordered even numbers from 2
*
* #param num number of uniqe even digits
* #param array of size equal to the number
*
*/
void evenArrayGen(int num, int even_nums[]) {
int i, current;
i = current = 0;
for(; i<num; i++) {
even_nums[i] = current += 2;
}
return;
}
/** Shuffle the array in random order. Radomly gets the index between 0 and
* current last index. Swaps number at random index with last one and
* decreses the current_last index by 1.
*
* #param array of numbers to be shuffled
*
*/
void shuffle(int nums[]) {
int i, len, current_last, index, temp;
///set the current_last to length of the array to track index for
///swaping nums
current_last = len = SIZE;
for (i=0; i<len; i++) {
srand(time(NULL));
index = rand()%(current_last);
temp = nums[index];
nums[index] = nums[current_last];
nums[current_last] = temp;
current_last--;
}
return;
}
int main() {
//initialize root for the tree
Node *root;
//intilialize array of 5,000,000 elements, and scores
static int nums[SIZE];
int i; //iterator
//initialize positive and negative numbers for find method
int positive_num, negative_num;
//initilaize timer
clock_t start_for_adding, start_for_finding;
//add elements to the array
evenArrayGen(SIZE, nums);
shuffle(nums);
//set positive number to one of the first 5000 elements
positive_num = nums[3222];
negative_num = 345; //all numbers in num are even so negative need to be odd
root = NULL; //set the root Node to NULL
start_for_adding = clock(); //zero the timer
//now iterate trough all elements in nums array and add each to
//the binary tree
for(i=0; i<SIZE; i++) {
//check if i reached proper value
if (i == 5000 || i == 50000 || i == 500000 || i == (5000000-1)) {
//add the adding time
printf("\nIndex: %d\n", i);
printf("Adding: %.5f\n", (double) clock() - start_for_adding);
start_for_finding = clock(); //zero the timer
//search for positive num
findNode(root, positive_num);
printf("Finding positive: %.5f\n",
(double) clock() - start_for_finding);
start_for_finding = clock(); //zero the timer
//search for negative num
findNode(root, negative_num);
printf("Finding negative: %.5f\n",
(double) clock() - start_for_finding);
start_for_adding = clock(); //reset the timer for adding
}
addNode(&root, nums[i]);
}
return;
}
The times for finding elements are pointing to zero (in both cases)
I'm pretty lost, have no idea where to follow now (the easiest part for my task shows that is the hardest one...)
The resolution of clock is most likely to coarse to measure the time taken by individual calls to your findNode function. Typically the time is measured to perform such a call lots of times and then divide this time by the number of times the call was performed.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
I am trying to find a BFS algorithm in C but I can't find one that actually works. I have a binary heap (tree implementation) and what I want to do is use the BFS algorithm in order to find the right place to insert a new element in my tree.
P.S I don't know the exact number of the elements that will be inserted (if that helps).
The procedure for inserting into an array-based binary heap is:
Add the new item to the end of the heap
Bubble it up
In an array implementation, adding to the end of the heap is trivial.
In a tree based implementation, you determine the path to the node and then traverse that path from the root down, sifting as you go. You have to know how many items are already in the heap, and that the tree is correctly balanced when you start.
Say, for example that there are 4 nodes in the heap:
0
1 2
3
The next node you add will go into position 4--the right child of node 1. So your job is to determine where position 4 is. More correctly, you have to determine which node is the parent of position 4.
If the root node is 0, then the parent of any node is node (i-1)/2. So the parent of node 4 is node 1, and the parent of node 1 is node 0.
You can write a recursive function that, given a node number, will traverse the tree to find the path to the parent. On the way out of the recursion, you actually end up sifting the node down the tree rather than bubbling it up, but the complexity is the same: O(log n).
Note that this doesn't do a breadth-first search. BFS would be a horribly inefficient way to do things.
Additional info
There's no special handling required for "even" or "odd" cases. It's all implicit in the tree structure. Consider this method, which will give you the path from the root to the insertion point in the tree:
(My example is in C#, simply because that's what I'm using these days. You should be able to convert to C with little trouble.)
private void HeapInsert(int node)
{
if (node == 0)
return;
int parent = (node - 1)/2;
HeapInsert(parent);
Console.WriteLine("From node {0}, take {1} child to node {2}", parent, (node%2) == 0 ? "right" : "left", node);
}
I've simplified it in that it just shows the integer node numbers rather than doing the actual heap insertion. You can easily modify the code so that rather than outputting the path it, it gives you the actual nodes in the path from root to the insertion point.
Depending on your implementation, you can then traverse that path, insert the node in the proper place, and then bubble it up. Or, you can traverse the path from root to leaf, sifting the new item down in the process.
Insert into a binary heap need not use BFS.
What about generic implementation taken from program appearing in book:
"Programming Challenges: The Programming Contest Training Manual" by
Steven Skiena and Miguel Revilla, Springer-Verlag, New York 2003.
#define TRUE 1
#define FALSE 0
#define MAXV 100 /* maximum number of vertices */
#define MAXDEGREE 50 /* maximum outdegree of a vertex */
typedef struct {
int edges[MAXV+1][MAXDEGREE]; /* adjacency info */
int degree[MAXV+1]; /* outdegree of each vertex */
int nvertices; /* number of vertices in the graph */
int nedges; /* number of edges in the graph */
} graph;
#define QUEUESIZE 1000
typedef struct {
int q[QUEUESIZE+1]; /* body of queue */
int first; /* position of first element */
int last; /* position of last element */
int count; /* number of queue elements */
} queue;
typedef int bool;
bool processed[MAXV]; /* which vertices have been processed */
bool discovered[MAXV]; /* which vertices have been found */
int parent[MAXV]; /* discovery relation */
bool finished = FALSE; /* if true, cut off search immediately */
initialize_search(graph *g)
{
int i; /* counter */
for (i=1; i<=g->nvertices; i++) {
processed[i] = discovered[i] = FALSE;
parent[i] = -1;
}
}
bfs(graph *g, int start)
{
queue q; /* queue of vertices to visit */
int v; /* current vertex */
int i; /* counter */
init_queue(&q);
enqueue(&q,start);
discovered[start] = TRUE;
while (empty(&q) == FALSE) {
v = dequeue(&q);
process_vertex(v);
processed[v] = TRUE;
for (i=0; i<g->degree[v]; i++)
if (valid_edge(g->edges[v][i]) == TRUE) {
if (discovered[g->edges[v][i]] == FALSE) {
enqueue(&q,g->edges[v][i]);
discovered[g->edges[v][i]] = TRUE;
parent[g->edges[v][i]] = v;
}
if (processed[g->edges[v][i]] == FALSE)
process_edge(v,g->edges[v][i]);
}
}
}
/*
bool valid_edge(edge e)
{
if (e.residual > 0) return (TRUE);
else return(FALSE);
}
*/
dfs(graph *g, int v)
{
int i; /* counter */
int y; /* successor vertex */
if (finished) return; /* allow for search termination */
discovered[v] = TRUE;
process_vertex(v);
for (i=0; i<g->degree[v]; i++) {
y = g->edges[v][i];
if (valid_edge(g->edges[v][i]) == TRUE) {
if (discovered[y] == FALSE) {
parent[y] = v;
dfs(g,y);
} else
if (processed[y] == FALSE)
process_edge(v,y);
}
if (finished) return;
}
processed[v] = TRUE;
}
find_path(int start, int end, int parents[])
{
if ((start == end) || (end == -1))
printf("\n%d",start);
else {
find_path(start,parents[end],parents);
printf(" %d",end);
}
}
/*The testing part*/
process_vertex(int v)
{
printf("processed vertex %d\n",v);
}
process_edge(int x, int y)
{
printf("processed edge (%d,%d)\n",x,y);
}
bool valid_edge(int e)
{
return (TRUE);
}
int main()
{
graph g;
int i;
read_graph(&g,FALSE);
print_graph(&g);
initialize_search(&g);
bfs(&g,1);
for (i=1; i<=g.nvertices; i++)
printf(" %d",parent[i]);
printf("\n");
for (i=1; i<=g.nvertices; i++)
find_path(1,i,parent);
printf("\n");
return 0;
}
here is graph part:
initialize_graph(graph *g)
{
int i; /* counter */
g -> nvertices = 0;
g -> nedges = 0;
for (i=1; i<=MAXV; i++) g->degree[i] = 0;
}
read_graph(graph *g, bool directed)
{
int i; /* counter */
int m; /* number of edges */
int x, y; /* vertices in edge (x,y) */
initialize_graph(g);
scanf("%d %d",&(g->nvertices),&m);
for (i=1; i<=m; i++) {
scanf("%d %d",&x,&y);
insert_edge(g,x,y,directed);
}
}
insert_edge(graph *g, int x, int y, bool directed)
{
if (g->degree[x] > MAXDEGREE)
printf("Warning: insertion(%d,%d) exceeds max degree\n",x,y);
g->edges[x][g->degree[x]] = y;
g->degree[x] ++;
if (directed == FALSE)
insert_edge(g,y,x,TRUE);
else
g->nedges ++;
}
delete_edge(graph *g, int x, int y, bool directed)
{
int i; /* counter */
for (i=0; i<g->degree[x]; i++)
if (g->edges[x][i] == y) {
g->degree[x] --;
g->edges[x][i] = g->edges[x][g->degree[x]];
if (directed == FALSE)
delete_edge(g,y,x,TRUE);
return;
}
printf("Warning: deletion(%d,%d) not found in g.\n",x,y);
}
print_graph(graph *g)
{
int i,j; /* counters */
for (i=1; i<=g->nvertices; i++) {
printf("%d: ",i);
for (j=0; j<g->degree[i]; j++)
printf(" %d",g->edges[i][j]);
printf("\n");
}
}
here is queue
init_queue(queue *q)
{
q->first = 0;
q->last = QUEUESIZE-1;
q->count = 0;
}
enqueue(queue *q, int x)
{
if (q->count >= QUEUESIZE)
printf("Warning: queue overflow enqueue x=%d\n",x);
else {
q->last = (q->last+1) % QUEUESIZE;
q->q[ q->last ] = x;
q->count = q->count + 1;
}
}
int dequeue(queue *q)
{
int x;
if (q->count <= 0) printf("Warning: empty queue dequeue.\n");
else {
x = q->q[ q->first ];
q->first = (q->first+1) % QUEUESIZE;
q->count = q->count - 1;
}
return(x);
}
int empty(queue *q)
{
if (q->count <= 0) return (TRUE);
else return (FALSE);
}
print_queue(queue *q)
{
int i,j;
i=q->first;
while (i != q->last) {
printf("%c ",q->q[i]);
i = (i+1) % QUEUESIZE;
}
printf("%2d ",q->q[i]);
printf("\n");
}
use this function
void bfs(int v)
{
for(i=1;i<=n;i++)
if(a[v][i] && !visited[i])
q[++r]=i;
if(f<=r)
{
visited[q[f]]=1;
bfs(q[f++]);
}
}
Recursion might solve your problem
I'm trying to replace cycle in the graph to a group of the vertexes (remove this cycle and put there once vertex with maximum number)
struct group {
int master; // representative of cycle
};
struct vertex {
int *to; // neighbor list
int nb; // how many neighbor
int p; // parent
short v; // was visited? 0 = false, 1 = true
struct group *cycle; // is part of cycle? NULL = no, else pointer to group
};
I'm running dfs on each vertex
void searchCycles() {
int i;
for (i = 0; i < MAX_VER; i += 1)
if (ver[i].v == 0 && ver[i].nb > 0)
dfs(i);
}
dfs:
void dfs(int v) {
ver[v].v = 1;
int i;
for (i = 0; i < ver[v].nb; i += 1) {
ver[ver[v].to[i]].p = v;
if (ver[ver[v].to[i]].v == 0)
dfs(ver[v].to[i]);
else
// cycle found
replaceCycle(ver[v].to[i]);
}
}
and replace function shout print what vertexes are in cycle
void replaceCycle(int v) {
struct group *g = &gr[usedGroup++];
g->master = -1;
printf("\nCYKL: %d ", v);
int p = ver[v].p;
while (p != v) {
printf("%d(%d) ", p, v);
p = ver[p].p;
}
printf("\n");
}
Generally it's works, but sometimes it get a infinity loop. I tried to debug it and if there are two or more cycles, parents (p in vertex struct) are lost, it's means it works fine but there is wrong number. I'm learning C and algorithms, so I don't know a lot of it.
It's not a homework, it's a spoj problem
Once you replace a cycle, restart your dfs.
Basically, the visited flag might be set for your first cycle, but you'd want that cleared to test your second cycle. (And third, and fourth, etc.)
i have 2 int arrays i need to print all the identical integers in O(nlogn)
the arrays are not sorted and after sorting can be:
X [ 1,2,3,4,5,6,7,8,9]
Y [1,2,8,9]
so checking only till the 4 place(the size of the smaller array) is not an option.
what kind of loop\equation do i need to use so it would be nlogn
?
if i will run the for till the last value of the smaller array -will it still be nlogn-
how can i take\reach only the last integer in arraya without running till the end of it?
I'm hoping this is enough of a hint...
Once the arrays are sorted, just walk through the arrays 'side-by-side'. Keep track of the 'current' element for each array (X and Y). You might do this using an index variable for each array or by using a pointer. Personally, I'd find it easier to use pointers, but you or your friend may have a different preference.
For each pair of 'current' elements, if the elements match then print the value. Then consider what needs to be done, if anything, to move to the next element of each array (for the cases where the elements don't match as well as for the case where they do match). There are only three cases:
x[cur_x] == y[cur_y]
x[cur_x] < y[cur_y]
y[cur_y] < x[cur_x]
so it shouldn't be too difficult to determine what should be done in each case.
Sorting the arrays in an O(n log n) operation. Walking through the arrays is an O(n) operation, so altogether it's an O(n) + O(n log n) operation, which reduces down to O(n log n). In other words, the overall time complexity of the operation is determined by the sort operation.
Using a binary search will also work, but it might be a little more complicated - especially to properly handle duplicated elements in the arrays if that's a requirement (and depending on what 'properly' might mean according to the requirements).
You can take the smaller array and search each element in the bigger element with binary search
for(int i = 0; i < size1; i++) {
binarysearch(arr_small[i], arr_big);
}
binary search requires O(log n) time for each search. Total search time for all elements is O(nlogn)
If you dont remember binary search, refer the link: http://en.literateprograms.org/Binary_search_(C)
throw one array in a hash. Look up the other array in the hash. But that's not nlogn.. it's m+n.
This approach does not need the X and Y to be sorted.
Add the elements of X to a binary search tree (avoid duplicate entries, i.e. if X[0] = 1 and X[1] = 1 then don't add X[1]; just ignore it).
Then try to add the contents of Y to the same binary search tree and If you find the element already in there, then its identical.
The total time complexity boils down to the time complexity of adding element to BST which is O(n log n) but worst case would be O(n) if the tree is skewed (i.e. if the arrays are sorted).
Here is the code for your reference!
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
typedef struct node {
int data;
struct node *left;
struct node *right;
} NODE;
NODE *root = NULL;
NODE * newnode (int data)
{
NODE * n = NULL;
if (n = (NODE *) malloc (sizeof (NODE))) {
n->data = data;
n->right = n->left = NULL;
} else {
printf("%d - %d - unalbe to create new node \n", __LINE__, data);
}
return n;
}
NODE * getnode(NODE * n, int data)
{
if (n == NULL)
return NULL;
if (n->data == data)
return n;
if (data < n->data) {
return getnode (n->left, data);
}
if (data > n->data) {
return getnode (n->right, data);
}
return NULL;
}
NODE * insert (NODE * node, int data, int *dup)
{
NODE * n = NULL;
if (node != NULL) {
if (getnode(node, data) != NULL) {
/* element already present in the tree..
so set the dup and return the root */
*dup = 1;
return node;
}
}
if (node == NULL) {
n = newnode(data);
return (n);
}
if (data <= node->data)
node->left = insert(node->left, data, dup);
else
node->right = insert(node->right, data, dup);
return node;
}
NODE * deletetree(NODE * from)
{
if (from != NULL) {
deletetree(from->left);
deletetree(from->right);
//printf("deleting %d \n", from->data);
free(from);
}
return NULL;
}
int main()
{
int sum = 35;
int X[] = {1,2,3,4,5,6,7,8,9,1,2,3,4,5};
int Y[] = {1,2,8,9};
int i, dup = 0;
int xlen = sizeof(X)/sizeof(X[0]);
int ylen = sizeof(Y)/sizeof(Y[0]);
printf("len of X is : %d \n", xlen);
printf("len of Y is : %d \n", ylen);
NODE * root1 = NULL;
for (i=0; i<xlen; i++) {
root = insert(root, X[i], &dup);
}
for (i=0; i<ylen; i++) {
dup = 0;
root = insert(root, Y[i], &dup);
if (dup == 1) {
printf("%d ", Y[i]);
}
}
printf("\n");
root = deletetree(root);
return 0;
}