BST and Linked List C program stuck at large values - c

I'm doing a college work where the professor asked us to implement BST and linked list and count how many comparisons it makes to insert and search a large amount of randomly-generated values. We're supposed to start at 10 values, then 100, then 1000, up until 10^12. The thing is, it always gets stuck at 100000 (10^5). The RAM usage is low, but CPU is at max. I'm freeing both the tree and lists after each step. The code is found here (offsite) and below.
Just to sum up some important points: each value (the key to the node) is an unsigned it (max 65535), but up to 10^12 values should be inserted and another 10^12 searched.
Is it supposed to take this long? My processor is an i5-7200u
Is there a chance it's a memory problem and GCC is blocking it somehow?
Thanks a lot
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef long long ll;
typedef unsigned long long ull;
// BST
typedef struct no_A_struct {
unsigned int chave;
struct no_A_struct *esquerda;
struct no_A_struct *direita;
} no_A;
// new node
no_A *novo_no_A(unsigned int chave) {
no_A *no = (no_A *) malloc(sizeof(no_A));
no->chave = chave;
no->esquerda = no->direita = NULL;
return no;
}
// insert note
no_A *insere_A(no_A *raiz, unsigned int chave, ull *cont) {
(*cont)++; if (raiz == NULL) return novo_no_A(chave);
(*cont)++; if (chave < raiz->chave) raiz->esquerda = insere_A(raiz->esquerda, chave, cont);
else {
(*cont)++; if (chave > raiz->chave) raiz->direita = insere_A(raiz->direita, chave, cont);
}
return raiz;
}
// search node
no_A *busca_A(no_A *raiz, unsigned int chave, ull *cont) {
(*cont)++; if (raiz == NULL) return NULL;
(*cont)++; if (chave == raiz->chave) return raiz;
(*cont)++; if (chave > raiz->chave) return busca_A(raiz->direita, chave, cont);
return busca_A(raiz->esquerda, chave, cont);
}
// free tree
void desaloca_A(no_A *raiz) { // TODO iterativa?
if (raiz == NULL) return;
desaloca_A(raiz->esquerda);
desaloca_A(raiz->direita);
free(raiz);
}
// LINKED LIST WITH IN ORDER INSERTION
typedef struct no_L_struct {
unsigned int chave;
struct no_L_struct *prox;
} no_L;
// new node
no_L *novo_no_L(unsigned int chave) {
no_L *no = (no_L *) malloc(sizeof(no_L));
no->chave = chave;
no->prox = NULL;
return no;
}
// insert node
void insere_L(no_L **inicio, unsigned int chave, ull *cont) {
no_L *novo_no = novo_no_L(chave);
(*cont)++; if (*inicio == NULL) { *inicio = novo_no; return; }
(*cont)++; if (novo_no->chave <= (*inicio)->chave) {
novo_no->prox = *inicio;
*inicio = novo_no;
} else {
no_L *atual = *inicio;
for (;;) {
(*cont)++; if (atual->prox == NULL) break;
(*cont)++; if (novo_no->chave <= atual->prox->chave) break;
atual = atual->prox;
}
novo_no->prox = atual->prox;
atual->prox = novo_no;
}
}
// search node
no_L *busca_L(no_L *atual, unsigned int chave, ull *cont) {
for (;;) {
(*cont)++; if (atual == NULL) break;
(*cont)++; if (atual->chave == chave) break;
atual = atual->prox;
}
return atual;
}
// void printa_L(no_L *atual) {
// if (atual == NULL) return;
// printf("%u", atual->chave);
// printa_L(atual->prox);
// }
// free list
void desaloca_L(no_L *atual) {
no_L *no_apagar;
while (atual != NULL) {
no_apagar = atual;
atual = atual->prox;
free(no_apagar);
}
}
int main() {
ll QTD_VALORES[] = {10, 100, 1000, // 10^: 1, 2, 3
10000, 100000, 1000000, // 4, 5, 6
1000000000, 10000000000, // 9, 10
100000000000, 1000000000000}; // 11, 12
int ITERACOES = 1; // TODO voltar pra 100
unsigned int VALOR_MAX = 65535;
int tamanho_qtd_valores = sizeof(QTD_VALORES)/sizeof(QTD_VALORES[0]);
srand(time(0));
for (int qtd_i=0; qtd_i<tamanho_qtd_valores; qtd_i++) {
ll qtd = QTD_VALORES[qtd_i];
printf("== QTD DE VALORES %lli ==\n", qtd);
for (int i=0; i<ITERACOES; i++) {
ull comp_A_insercao = 0, comp_A_busca = 0,
comp_L_insercao = 0, comp_L_busca = 0;
no_A *arvore = NULL;
no_L *lista = NULL;
// generates and insert values
unsigned int valores_busca[qtd];
for (ll v=0; v<qtd; v++) {
// // insert values
unsigned int valor_insercao = rand() % VALOR_MAX + 1;
arvore = insere_A(arvore, valor_insercao, &comp_A_insercao);
insere_L(&lista, valor_insercao, &comp_L_insercao);
valores_busca[v] = rand() % VALOR_MAX + 1;
}
// search values
for (ll v=0; v<qtd; v++) {
busca_A(arvore, valores_busca[v], &comp_A_busca);
busca_L(lista, valores_busca[v], &comp_L_busca);
}
// desaloca_A(arvore);
// desaloca_L(lista);
// TODO divisões retornar numero real?
printf("INTERACTION %d: \n", i+1);
printf("Tree insertion, total=%llu, avg=%llu\n", comp_A_insercao,
comp_A_insercao / qtd);
printf("Tree search, total=%llu, avg=%llu\n", comp_A_busca,
comp_A_busca / qtd);
printf("List insertion, total=%llu, avg=%llu\n", comp_L_insercao,
comp_L_insercao / qtd);
printf("List search, total=%llu, avg=%llu\n", comp_L_busca,
comp_L_busca / qtd);
}
printf("\n");
}
}

Are you sure you are supposed to insert items already in the list? I think you're suppose to avoid adding duplicates keys.
Inserting the first node in the linked list will requires 0 comparisons. The second, 1/2 (on avg). The third, 2/2, The fourth 3/2, etc. So inserting N times will have a average time proportional to (0+1+2+...+(N-2)+(N-1))/2 = N*(N-1)/4.
$ perl -e'printf "%d: %d\n", $_, (10**$_)*(10**$_-1)/4 for 1..5;'
1: 22
2: 2475
3: 249750
4: 24997500
5: 2499975000
That's an average time of 2.5 billion time units to insert 105 nodes. For example, if it takes 100 ns per comparison, it will take over 4 minutes to insert 105 nodes on average.
At that same rate, inserting 1012 nodes would take an average of 800 million years.
If, on the other hand, you avoid adding a key that's already in the list, the average time will be no more than 65,536*N/2
$ perl -e'printf "%d: %d\n", $_, 65536*(10**$_-1)/4 for 1..12;'
1: 147456
2: 1622016
3: 16367616
4: 163823616
5: 1638383616
6: 16383983616
7: 163839983616
8: 1638399983616
9: 16383999983616
10: 163839999983616
11: 1638399999983616
12: 16383999999983616
So instead of taking 800 million years, inserting 1012 nodes will take an average of "only" 19 days using the rate assumed above. Even if I'm off by an order of magnitude, we're still talking about 2 days.

Related

Check if undirected graph is connected

I have been making an algorithm that builds a Minimum Spanning Tree where I insert the number of cities (vertexes), airports (edges connecting to a "sky" vertex - vertex 0) and the number of roads (edges connected to other cities).
I then insert the city the airport (source vertex) is built and the cost (edge cost).
After this, I insert the cities connected by roads (source and destiny vertexes) and the cost (edge cost).
The outputs are the MST cost, the number of airports and number of roads.
I already have these mechanisms working but they are a bit buggy. I can't seem to fix these issues.
Also, I was wondering if I can make a function that detects if the undirected graph in the MST is connected (all vertexes are connected). If the function detects that the MST is not connected, the program should output "Insuficient information.".
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// A structure to represent a weighted edge in graph.
struct Edge {
int src, dest, weight;
};
// A structure to represent a connected, undirected and weighted graph.
struct Graph {
// V -> Vertex Number (Number of cities), E -> Number of edges (Number of roads + airport connections).
int V;
int E;
// The graph is represented as an array of edges.
// Since the graph is undirected, the edge
// from src to dest is also edge from dest
// to src. Both are counted as 1 edge here.
struct Edge* edge;
};
// Creates a graph with V vertexes and E edges.
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = malloc(sizeof *graph);
graph->V = V;
graph->E = E;
graph->edge = (struct Edge*)malloc(E * sizeof(struct Edge));
return graph;
};
// A structure to represent a subset for union-find.
struct subset {
int parent;
int rank;
};
// A utility function to find set of an element (uses path compression technique).
int find(struct subset subsets[], int i)
{
// Find root and make root as parent of i (uses path compression technique).
if (subsets[i].parent != i)
subsets[i].parent
= find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// A function that does union of two sets of x and y (uses union by rank).
void Union(struct subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
// Attach smaller rank tree under root of high rank tree (Union by Rank).
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
// If ranks are same, then make one as root and increment its rank by one.
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
// Compare two edges according to their weights.
// Used in qsort() for sorting an array of edges.
int myComp(const void* a, const void* b)
{
struct Edge* a1 = (struct Edge*)a;
struct Edge* b1 = (struct Edge*)b;
if (a1->weight > b1->weight) {
return a1->weight > b1->weight;
}
if (a1->weight < b1->weight) {
return a1->weight < b1->weight;
}
if (a1->weight == b1->weight) {
return a1->weight == b1->weight;
}
}
// The main function to construct MST using Kruskal's algorithm.
void KruskalMST(struct Graph* graph)
{
int V = graph->V;
struct Edge
result[V]; // Saves the resulting MST.
int e = 0; // An index variable, used for result[].
int i = 0; // An index variable, used for sorted edges.
// Step 1: Sort all the edges in non-decreasing order of their weight.
// If we are not allowed to change the given graph, we can create a copy of array of edges.
qsort(graph->edge, graph->E, sizeof(graph->edge[0]),
myComp);
// Allocate memory for creating V ssubsets.
struct subset* subsets
= (struct subset*)malloc(V * sizeof(struct subset));
// Create V subsets with single elements.
for (int v = 0; v < V; ++v) {
subsets[v].parent = v;
subsets[v].rank = 0;
}
// Number of edges to be taken is equal to V-1.
while (e < V - 1 && i < graph->E) {
// Step 2: Pick the smallest edge.
// And increment the index for next iteration.
struct Edge next_edge = graph->edge[i++];
int x = find(subsets, next_edge.src);
int y = find(subsets, next_edge.dest);
// If including this edge does't cause cycle,
// include it in result and increment the index
// of result for next edge.
if (x != y) {
result[e++] = next_edge;
Union(subsets, x, y);
}
// Else discard the next_edge.
}
int minimumCost = 0;
int nRoads = 0;
int nAirports = 0;
for (i = 0; i < e; ++i)
{
if (result[i].dest == 0) {
nAirports++;
} else {
nRoads++;
}
minimumCost += result[i].weight;
}
printf("Minimum Spanning Tree with minimal cost: %d\n",minimumCost);
printf("Number of airports: %d\n",nAirports);
printf("Number of roads: %d",nRoads);
return;
}
int main()
{
int v = 0; // Number of vertexes(cities) in the graph (includes the "sky" vertex).
int a = 0; // Number of airports.
int edges = 0; // Number of roads.
int e = 0; // Number Total number of edges in the graph.
int city = 0;
int airport = 0;
int city1 = 0;
int city2 = 0;
int cost = 0;
printf("Input the number of cities: \n");
scanf("%d", &v);
printf("Input the number of airports: \n");
scanf("%d", &a);
printf("Input the number of roads: \n");
scanf("%d", &e);
edges = a + e;
if (a > 0) {
v = v + 1;
}
struct Graph* graph = createGraph(v, edges);
for (int i = 0; i < a; i++) {
printf("Input the city and the building cost of the airport: \n");
scanf("%d %d", &city, &airport);
graph->edge[i].src = city;
graph->edge[i].dest = 0; // "sky" vertex.
graph->edge[i].weight = airport;
}
for (int j = a; j < edges; j++) {
printf("Input the cities and the cost of the road: \n");
scanf("%d %d %d", &city1, &city2, &cost);
if (a == 0) {
graph->edge[j].src = city1 - 1;
graph->edge[j].dest = city2 - 1;
graph->edge[j].weight = cost;
} else {
graph->edge[j].src = city1;
graph->edge[j].dest = city2;
graph->edge[j].weight = cost;
}
}
KruskalMST(graph);
return 0;
}
Example of a bug - 0 airports declared but still counts an airport:
Input the number of cities:
4
Input the number of airports:
0
Input the number of roads:
4
Input the cities and the cost of the road:
1 2 1
Input the cities and the cost of the road:
2 3 2
Input the cities and the cost of the road:
3 4 1
Input the cities and the cost of the road:
4 1 1
Minimum Spanning Tree with minimal cost: 3
Number of airports: 1
Number of roads: 2
The expected number of airports should be 0.

Kruskal alghoritm - working but difficult

I was working on Kruskal algorithm that will read input and based on this information it will find the shortest path between every two nodes.
Let me explain:
There are numbers on the input, for example:
7 6 1 5
1 7 20
7 2 5
2 3 9
4 2 4
5 2 7
6 5 3
On the first line there are 4 numbers = number of nodes, number of edges, beginning node (where to start), end node (where to end).
On the rest of lines are 3 numbers = one node(lets say x), second node(y), length between them.
The input will give me shortest path between the start and end node.
In this example case it would be number 32.
I have a fully working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct edge{
int goal, length;
struct edge *p_next;
} EDGE;
typedef struct node{
int name;
EDGE *p_edges, *last;
} NODE;
int helper;
int getDist(int size, NODE *nodes[size+1], int from, int act, int goal)
{
EDGE *p_act;
for(p_act = nodes[act]->p_edges; p_act != 0; p_act = p_act->p_next)
{
if (p_act->goal == goal)
{
return p_act->length;
}
if (p_act->goal != from)
{
helper = getDist(size, nodes, act, p_act->goal, goal);
}
if (helper != 0)
{
return helper + p_act->length;
}
}
return 0;
}
int main()
{
int numV, numH, start, goal, i, length, a, b;
EDGE *p_newEdge, *p_newEdge2;
scanf("%d %d %d %d", &numV , &numH, &start, &goal);
NODE *nodes [numV+1];
for(i = 0; i <= numV; i++)
{
nodes[i] = (NODE*)malloc(sizeof(NODE));
}
for(i = 0; i < numH; i++)
{
scanf("%d %d %d",&a,&b,&length);
p_newEdge = (EDGE*)malloc(sizeof(EDGE));
p_newEdge->length = length;
p_newEdge->goal = b;
p_newEdge2 = (EDGE*)malloc(sizeof(EDGE));
p_newEdge2->length = length;
p_newEdge2->goal = a;
if (nodes[a]->p_edges == 0)
{
nodes[a]->p_edges = p_newEdge;
nodes[a]->last = p_newEdge;
}
else if (nodes[a]->p_edges != 0)
{
nodes[a]->last->p_next = p_newEdge;
nodes[a]->last = nodes[a]->last->p_next;
}
if (nodes[b]->p_edges != 0)
{
nodes[b]->last->p_next = p_newEdge2;
nodes[b]->last = nodes[b]->last->p_next;
}
else if (nodes[b]->p_edges == 0)
{
nodes[b]->p_edges = p_newEdge2;
nodes[b]->last = p_newEdge2;
}
}
printf("%d\n",getDist(numV ,nodes, 0, start, goal));
return 0;
}
But my professor told me that it is very long and I should make it more simple (this was my third attempt and for my professor it is still too long and "complex").
I have no idea how to make it more simple.
Can someone help me with this?

QuickSorting Linked Lists in C

I am trying to become more familiar with recursion and I am trying to write a function recursively rather than iteratively... I am trying to create a quick-sort function for linked list, I keep reevaluating the code, but I don't know what I am missing, the code always leaves the last node on the list, for example...
input list ... 1->2->3->4->NULL
output list .. 4->NULL
here is my code ...
void lst_qsort(LIST *l){
if(l==NULL || l->front==NULL || l->front->next==NULL)
return;
if(lst_length(l)<=1)
return;
LIST *lt = lst_create();
LIST *pivot = lst_create();
pivot->front = l->front;
pivot->back = l->front;
l->front = l->front->next;
pivot->front->next = NULL;
lt = lst_filter_leq(l, pivot->front->val);
lst_qsort(lt);
lst_qsort(l);
lst_concat(l, lt);
}
NOTES lst_filter_leq() is a function that pulls out all occurrences of x<=cutoff point and returns a list of all the nodes pulled.
LIST * lst_filter_leq(LIST *lst, ElemType cutoff) {
LIST *lst2 = lst_create();
NODE *tmp = lst->front;
int i = 0, n=1;
while(lst->front != NULL){
if(lst->front->val <= cutoff){
lst_push_back(lst2, lst->front->val);
}
lst->front = lst->front->next;
}
lst->front = tmp;
for(i=cutoff; i>=0; i--){
n = lst_remove_all_slow(lst, i);
}
return lst2;
}
lst_concat() merges two list together
Look at your code and your example. First, looks like creating pivot list is seemingly not necessary, as you use only pivot->front->val, which I assume is the first value on your list (because you earlier did pivot->front = l->front).
So for values [1, 2, 3, 4] you do the following in the first step (I use pseudo-code to show list members):
// you extracted '1' from your list, because you did l->front = l->front->next;
lt = lst_filter_leq([2, 3, 4], 1);
which means you end with nothing (none of the values on the list are less or equal than 1). Next you do quicksort of l (which is [2, 3, 4]) and then concatenate results of l and lt.
But when quicksorting [2, 3, 4] you receive nothing and quicksort [3, 4],
which is nothing and [4].
And quicksorting of [4] returns [4]. Hence your result.
So looks what you forgot was inserting pivot between l and lt lists.
Working implementation using glib library for double-ended queues:
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
// defines to maintain compatibility with OP code
#define LIST GQueue
#define lst_create g_queue_new
#define lst_length g_queue_get_length
// lst_push_back implementation using GQueue
void lst_push_back(LIST *list, int val) {
g_queue_push_tail(list, GINT_TO_POINTER(val));
}
// lst_pop_front implementation using GQueue
int lst_pop_front(LIST *list) {
return GPOINTER_TO_INT(g_queue_pop_head(list));
}
// adds elements from list2 to list1
// list2 is destroyed afterwards
void lst_concat(LIST *list1, LIST *list2) {
int length = lst_length(list2);
int i, v;
for (i = 0; i < length; ++i) {
v = lst_pop_front(list2);
lst_push_back(list1, v);
}
g_queue_free(list2);
}
// filters 'list' elements
// elements less or equal 'value' are returned in newly created list
// elements greater than 'value' are left in 'list'
LIST *lst_filter_leq(LIST *list, int value) {
LIST *lte = lst_create();
LIST *gt = lst_create();
int length = lst_length(list);
int i, v;
for (i = 0; i < length; ++i) {
v = lst_pop_front(list);
if (v <= value) {
lst_push_back(lte, v);
} else {
lst_push_back(gt, v);
}
}
lst_concat(list, gt);
return lte;
}
void lst_qsort(LIST *l) {
if (l == NULL) {
return;
}
if (lst_length(l) <= 1) {
return;
}
LIST *lt = lst_create();
LIST *pivot = lst_create();
int val = lst_pop_front(l);
lst_push_back(pivot, val);
// this function divides the list int two parts
// elements less or equal 'val' are returned in lt list ("right" list)
// elements greater than 'val 'are left in l list ("left" list)
lt = lst_filter_leq(l, val);
lst_qsort(lt); // sort "right" part of list
lst_qsort(l); // sort "left" part of list
lst_concat(l, pivot); // add the pivot element
lst_concat(l, lt); // add right part of list
}
void printList(LIST *list) {
GList *vList = g_queue_peek_head_link(list);
while (vList != NULL) {
printf("%d", GPOINTER_TO_INT(vList->data));
vList = g_list_next(vList);
if (vList != NULL) {
printf("->");
} else {
printf("\n");
}
}
}
int main(void) {
LIST *l = lst_create();
lst_push_back(l, 4);
lst_push_back(l, 3);
lst_push_back(l, 2);
lst_push_back(l, 1);
printf("unsorted: ");
printList(l);
lst_qsort(l);
printf("sorted: ");
printList(l);
g_queue_clear(l);
lst_push_back(l, 1);
lst_push_back(l, 2);
lst_push_back(l, 3);
lst_push_back(l, 4);
printf("unsorted: ");
printList(l);
lst_qsort(l);
printf("sorted: ");
printList(l);
g_queue_clear(l);
srand(time(NULL));
int i;
for (i = 0; i < 16; ++i) {
lst_push_back(l, rand() % 32);
}
printf("unsorted: ");
printList(l);
lst_qsort(l);
printf("sorted: ");
printList(l);
g_queue_free(l);
return 0;
}
Example output:
unsorted: 4->3->2->1
sorted: 4->3->2->1
unsorted: 1->2->3->4
sorted: 4->3->2->1
unsorted: 27->16->20->4->14->30->26->28->10->13->19->1->30->8->3->14
sorted: 30->30->28->27->26->20->19->16->14->14->13->10->8->4->3->1

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.

BFS algorithm in C [closed]

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

Resources