BFS algorithm in C [closed] - c

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

Related

BFS traversal, same node being accessed twice

I am trying to figure out how to write BFS algorithm in C
and I got this
typedef struct graph {
int numnodes;
int **edges;
} graph;
void bfs(graph *g, int start) {
int visited[g->numnodes], queue[g->numnodes], front =- 1, rear =- 1;
for (int i = 0; i < g->numnodes; i++) {
visited[i] = 0;
}
front++;
queue[++rear] = start;
visited[start] = 1;
while (front <= rear) {
start = queue[front++];
printf("%d\t", start);
for (int i = 0; i < g->numnodes; i++) {
if (g->edges[start][i] == 1 && !visited[i]) {
queue[++rear] = i;
}
}
}
}
for graph looking like graph.
When I print out BFS, it seems to give me
0 1 2 2 3 4
I'm not entirely sure what's wrong here, some help would be appreciated.
I am not sure if BFS is the right term for what you are doing. Your graph is not a tree and with a node having multiple parent nodes it is hard to tell on what level a node really is.
But to make your code work as expected, you just need to fix your missing use of visited array:
if (g->edges[start][i] == 1 && !visited[i]) {
queue[++rear] = i;
visited[i] = 1;
}
Create an actual graph and go through that (e.g. struct for each node, nodes linked via pointers). Right now what you have is an array that you go through item by item if I understand correctly.
You can use an array to store one level of the graph.
0 (first level)
2 1 (second level)
...

Implementing Binary search tree using array in C

I am trying to implement a binary search tree using a 1-D array. I'm familiar with the fact that the left node will be parent*2+1 and right node will be parent*2+2. I am using this concept to write the insertion function here:
int* insert(int tree[], int element){
int parent=0;
if(tree[parent]=='\0'){
tree[parent]=element;
return tree;
}
else{
if(element<tree[parent]){
parent=parent*2+1;
tree[parent]=insert(tree[parent], element);
}
else{
parent=parent*2+2;
tree[parent]=insert(tree[parent], element);
}
}
return tree;
}
However, I'm quite sure this won't work, since I'm passing an element of the array into the insert() function while recursing, when it actually needs an array. I'm not sure how to go about it. Do I replace the return type from int* to int? Any help is appreciated
the fact that the left node will be parent2+1 and right node will be parent2+2
That's correct. You want to use the array index like
0
/ \
/ \
/ \
/ \
1 2
/ \ / \
/ \ / \
3 4 5 6
But your recursion is not doing that.
You always do int parent=0; so you have no knowledge of the real array index and consequently, you access the wrong array elements.
For instance:
When you pass tree[2] you really want the function to use either tree[5] or tree[6] in the next recursive call. However, since you start by setting parent to zero, your next recursive call will us either tree[3] or tree[4].
Conclusion If you want to use recursion, you need to track the actual array index of the current node. Simply passing a pointer to the current node is not sufficient.
Instead your code could be:
int insert(int* tree, unsigned current_idx, int element){
if (current_idx >= ARRAY_SIZE) return -1;
if(tree[current_idx]=='\0'){
tree[current_idx]=element;
return 0;
}
if(element<tree[current_idx]){
return insert(tree, 2*current_idx + 1, element);
}
return insert(tree, 2*current_idx + 2, element);
}
That said - you should also spend some time considering whether recursion is really a good solution for this task.
Without recursion you can do:
int insert(int* tree, int element){
unsigned current_idx = 0;
while (1)
{
if (current_idx >= ARRAY_SIZE) return -1;
if(tree[current_idx]=='\0'){
tree[current_idx]=element;
return 0;
}
if(element<tree[current_idx]){
current = 2*current_idx + 1;
}
else {
current = 2*current_idx + 2;
}
}
}
As you can see the recursive approach didn't give you anything. Instead it made things worse...
You can avoid recursion and do it iteratively. Note tree is actually an integer array of size size. In the function insert() we pass a pointer to the array. Assuming the array is initialized with 0s:
void insert(int* tree, int size, int element)
{
if (tree == NULL)
return;
int pos = 0;
while (pos < size)
{
if (tree[pos])
{
if (tree[pos] < element)
pos = 2 * pos + 2; // right
else if (tree[pos] && tree[pos] > element)
pos = 2 * pos + 1; // left
}
else
{
tree[pos] = element;
return;
}
}
}
Full code:
#include <stdio.h>
#include <stdlib.h>
void insert(int* tree, int size, int element)
{
if (tree == NULL)
return;
int pos = 0;
while (pos < size)
{
if (tree[pos])
{
if (tree[pos] < element)
pos = 2 * pos + 2; // right
else if (tree[pos] && tree[pos] > element)
pos = 2 * pos + 1; // left
}
else
{
tree[pos] = element;
return;
}
}
}
void print(int* tree, int size)
{
for (int i = 0; i < size; i++)
printf("%d ", tree[i]);
printf("\n");
}
int main()
{
int tree[100] = {0};
const int tsize = 100;
// print first 20 elements
print(tree, 20);
insert(tree, tsize, 2);
insert(tree, tsize, 3);
insert(tree, tsize, 5);
insert(tree, tsize, 1);
insert(tree, tsize, 4);
print(tree, 20);
return 0;
}

Recursive Algorithm to count nodes less than the given value

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;
}

Measuring time in C

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.

replace/remove cycle in graph

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.)

Resources