How to permute(shuffle) dynamic/linked list in C - c

I use this data structure to store a graph:
struct Vertex
{
struct Line *a;
struct Line *b;
int X;
int Y;
struct Vertex *next;
struct Edge *edges;
int edgeCount;
};
struct Edge
{
struct Vertex *dst;
struct Vertex *src;
struct Edge *next;
float weight;
bool included;
bool visited;
};
I generate a linked list of vertices(the list is my graph) in a loop:
struct Edge *edge= malloc(sizeof(struct Edge));
////here I add edge's data
if(graph->edges == NULL)
{
graph->edges = edge;
}
else
{
edge->next = graph->edges;
}
And now I need to permute resulting array. It is simple with common array of integers:
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
void permutation(int* randomArray, int numIndex)
{
for (i = 0; i < numIndex; i++)
{
int randomOffset = rand() % (numIndex - i);
swap(randomArray[i], randomArray[i+randomOffset]);
}
}
But how to do the same with linked list?

Create an array of struct Edge * that contains all edges, built when the linked list is created, permute that array, rebuild the linked list.
The variables
struct Edge *pedges[MAXEDGES]; // or allocate dynamically (see below)
int nedges = 0;
then when list is created
struct Edge *edge= malloc(sizeof(struct Edge)); // your code
pedges[nedges++] = edge;
permutations are done the same way
void permuteEdges(struct Edge *pe, int ne) {
int i;
for (i = 0 ; i < ne ; i++) {
int randomOffset = rand() % (ne - i);
swap(pe[i], pe[i+randomOffset]);
}
}
finally, rebuild the linked list
for (i = 0 ; i < ne ; i++) {
if ( ! i) {
graph->edges = pe[i];
}
else {
pe[i-1]->next = pe[i];
}
}
ensure the last item next property points to NULL
pe[ne-1]->next = NULL;
Note that you could allocate pedges dynamically (to be freed after use). For instance if you use the array for a single shuffle, there is no need to keep that amount of memory in the heap.
Dynamic allocation
struct Edge *pedges = malloc(MAXEDGES * sizeof(*pedges));
...use it...
free(pedges);

Related

When resizing a hash table how to point to the new array of buckets

When testing my code it seems as though when I am resizing my bucket array the hash_table struct is not pointing to my new resized hash table. Is this the route to take when resizing a hash table? Or instead of having buck_array being hash_entry ** should it have been a hash_entry *
also hash_key() function gives the index in the bucket array based on char *string.
relevant structs:
typedef struct hash_entry_{
char *string;
void *data;
struct hash_entry_ *next;
}hash_entry;
typedef struct hash_table_{
hash_entry ** buck_array;
unsigned num_buckets;
} hash_table, *Ptrhash_table;
My resize function:
void resize_hash(Ptrhash_table table, int size) {
unsigned int old_Bnum = table->num_buckets;
table->num_buckets = size;
int i;
hash_entry *cur;
hash_entry **new_arr = (hash_entry **)calloc(size, sizeof(hash_entry));
for (i = 0; i < size; i++){
new_arr[i] = NULL;
}
for (i = 0; i <= old_Bnum; i++) {
while((table->buck_array[i]) != NULL){
cur = table->buck_array[i];
table->buck_array[i] = cur->next;
cur->next = new_arr[hash_key(table, cur->string)];
new_arr[hash_key(table, cur->string)] = cur;
}
}
free(table->buck_array);
table->buck_array = new_arr;
}

Problem with implementing a function to reverse a linked list in C

So I wanted to write a function to reverse a linked list using an array of pointers but I'm getting warnings: assignment from incompatible pointer type [-Wincompatible-pointer-types]. I wanted to store the pointers to nodes of the list in an array of pointers int **s = (int **)calloc(10, sizeof(int)); and thought that s[*top] = *l will assign the pointer to which **l is pointing to *topth element of array *s[]. So am I wrong thinking that elements of array *s[] are pointers? If someone could explain it to me I'd be very glad. Here's the whole code (except the part where I create the list which is fine):
typedef struct list {
int v;
struct list *next;
} list;
void reverseListS(list **l, int **s, int *top) {
while ((*l)->next != NULL) {
s[*top] = *l;
*top++;
*l = (*l)->next;
}
list *temp = *l;
while (!(*top == 0)) {
temp->next = s[*top];
*top--;
temp = temp->next;
}
temp->next = NULL;
}
int main() {
int **s = (int **)calloc(10, sizeof(int));
int *top = 0;
reverseListS(&l, s, top);
}
Many issues. Just in main: Should be sizeof(int *) (or sizeof *s). Although, I think you want s to be an array of ints, so it should be an int *. And top does not point anywhere - why is it even a pointer?. l is not initialized.
In reverseListS at s[*top] = *l; you are trying to assign a struct list * to an int *.
I have re-written your code to work. I'm not saying this is the best way to reverse a list, but it makes the fewest modifications to your code - as I understand it.
typedef struct list {
int v;
struct list *next;
} list;
void reverseListS(list **l)
{
// Count number of items
// *this step could be skipped by dynamically resizing the array with realloc
int count = 0;
list *temp = *l;
while (temp) {
count += 1;
temp = temp->next;
}
// Allocate memory - an array of list *
list **s = malloc(count * (sizeof *s));
if (!s) return;
// Copy list item addresses to array
temp = *l;
int index = 0;
while (temp) {
s[index++] = temp;
temp = temp->next;
}
// Rebuild the list in reverse order
// *if you already have an "append_to_list" function, that should be used here
temp = NULL;
for (int i = index - 1; i >= 0; i--) {
if (!temp) {
// This is the new first item in list.
// Make the original list point to it
*l = temp = s[i];
}
else {
// Append to end of new list
temp->next = s[i];
temp = s[i];
}
s[i]->next = NULL;
}
free(s);
}
int main() {
list *l;
// TODO: Fill the list with values.
reverseListS(&l);
}

Returning a list of numbers from a function in C using Struct

I'm trying to solve this codewars kata
Basically I need to wite a programe that spits out an array/list of numbers from a perticular range (of numbers) which have k primes multiplicatively.
countKprimes(5, 500, 600) --> [500, 520, 552, 567, 588, 592, 594]
Now my program "works" as in it can print the results correctly, but if I put it in codewars' answer area (without main of course), it just runs forever.
"Error code SIGKILL : Process was terminated. It took longer than 12000ms to complete"
This is the codewars template
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// In the preloaded section are some functions that can help.
// They can be used as a small library.
// There is no file to include, only the templates below.
struct node {
int data;
struct node *next;
};
struct list {
size_t sz;
struct node *head;
};
struct list* createList();
// push data at the head of the list
void insertFirst(struct list* l, int data);
struct list* reverse(struct list* l);
void listFree(struct list* l);
// functions to write
struct list* kPrimes(int k, int start, int nd)
{
// your code
}
And this is my code
#include <stdio.h>
struct list{
int a[600];
};
int smallestPrimeFactor(int number){
int x;
for(x = 2; x < number; x++) {
if(number % x == 0) {
return x;
}
}
return number;
}
int primefactors(int ofnumber){
static int counter = 0;
int tempcounter = counter;
int nextnumber = ofnumber/smallestPrimeFactor(ofnumber);
if(nextnumber != 1) {
if(ofnumber >= nextnumber) {
counter++;
primefactors(nextnumber);
}
}
return (counter - tempcounter) + 1;
}
struct list kPrimes(int k, int start, int nd){
int x, g = 0;
struct list ls;
for(x = start; x < nd; x++){
if(primefactors(x) == k){
ls.a[g] = x;
g++;
}
}
return ls;
}
int main(int argc, int **argv){
int p = 5, s = 500, e = 600;
int j = 0;
while(kPrimes(p, s, e).a[j] != '\0'){
printf("%d\n", kPrimes(p, s, e).a[j]);
j++;
}
}
I think the culprit here is
struct list{
int a[600];
};
Maybe while reading the array, the test file is overshooting a's index past '\0'.
I thought of a way of solving that by making a a pointer to integer but doing int *a; prints out nothing.
I know there are more than one way of returning an array. Using referance, using a static array, passing an array as argument, etc. But I want to solve this codewars' way. Think it'll be a nice learning experience.
So, how should I be using
struct node {
int data;
struct node *next;
};
struct list {
size_t sz;
struct node *head;
};
to solve the problem?
You should not bother about the structure themselves, you should simply use the provided functions:
struct list* kPrimes(int k, int start, int nd){
int x, g = 0;
struct list *ls = createList(); // 1. Create the list.
// 2. Maybe check if ls != NULL...
for(x = start; x < nd; x++){
if(primefactors(x) == k){
insertFirst(ls, x); // 3. Insert at the beginning.
g++;
}
}
struct list *rls = reverse(ls); // 4. Reverse the list.
listFree(ls); // 5. Free the original list.
return rls; // 6. Return the reversed list.
}
Since the functions reverse is not documented, I can only guess that it creates a new list without modifying the old one, which is why you need to free it after.
The createList(), insertFirst(), reverse(), and listFree() functions, as well as the function that consumes the return value of your function are all provided to you, and they all work with the types struct list and struct node. How, then, do you imagine it could work if you try to use a differently-defined struct list than those existing functions use?
So yes, you should be using the struct node and struct list types provided to you -- and the handy functions for manipulating them -- rather than defining different structure types with the same tags.

Memory leak of pointer to pointer

I am using the Dijkstra Algorithm with Adjacency List in this webpage. Since I want to build up different graphs and compute shortest paths many times, I add some "free" command to free the memory. However, the memory usage still increase after many iterations
Here are my modified code:
// C / C++ program for Dijkstra's shortest path algorithm for adjacency
// list representation of graph
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// A structure to represent a node in adjacency list
struct AdjListNode
{
int dest;
int weight;
struct AdjListNode* next;
};
// A structure to represent an adjacency liat
struct AdjList
{
struct AdjListNode *head; // pointer to head node of list
};
// A structure to represent a graph. A graph is an array of adjacency lists.
// Size of array will be V (number of vertices in graph)
struct Graph
{
int V;
struct AdjList* array;
};
// A utility function to create a new adjacency list node
struct AdjListNode* newAdjListNode(int dest, int weight)
{
struct AdjListNode* newNode =
(struct AdjListNode*) malloc(sizeof(struct AdjListNode));
newNode->dest = dest;
newNode->weight = weight;
newNode->next = NULL;
return newNode;
}
// A utility function that creates a graph of V vertices
struct Graph* createGraph(int V)
{
struct Graph* graph = (struct Graph*) malloc(sizeof(struct Graph));
graph->V = V;
// Create an array of adjacency lists. Size of array will be V
graph->array = (struct AdjList*) malloc(V * sizeof(struct AdjList));
// Initialize each adjacency list as empty by making head as NULL
for (int i = 0; i < V; ++i)
graph->array[i].head = NULL;
return graph;
}
// Adds an edge to an undirected graph
void addEdge(struct Graph* graph, int src, int dest, int weight)
{
// Add an edge from src to dest. A new node is added to the adjacency
// list of src. The node is added at the begining
struct AdjListNode* newNode = newAdjListNode(dest, weight);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
// Since graph is undirected, add an edge from dest to src also
newNode = newAdjListNode(src, weight);
newNode->next = graph->array[dest].head;
graph->array[dest].head = newNode;
}
// Structure to represent a min heap node
struct MinHeapNode
{
int v;
int dist;
};
// Structure to represent a min heap
struct MinHeap
{
int size; // Number of heap nodes present currently
int capacity; // Capacity of min heap
int *pos; // This is needed for decreaseKey()
struct MinHeapNode **array;
};
// A utility function to create a new Min Heap Node
struct MinHeapNode* newMinHeapNode(int v, int dist)
{
struct MinHeapNode* minHeapNode =
(struct MinHeapNode*) malloc(sizeof(struct MinHeapNode));
minHeapNode->v = v;
minHeapNode->dist = dist;
return minHeapNode;
}
// A utility function to create a Min Heap
struct MinHeap* createMinHeap(int capacity)
{
struct MinHeap* minHeap =
(struct MinHeap*) malloc(sizeof(struct MinHeap));
minHeap->pos = (int *)malloc(capacity * sizeof(int));
minHeap->size = 0;
minHeap->capacity = capacity;
minHeap->array =
(struct MinHeapNode**) malloc(capacity * sizeof(struct MinHeapNode*));
return minHeap;
}
// A utility function to swap two nodes of min heap. Needed for min heapify
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b)
{
struct MinHeapNode* t = *a;
*a = *b;
*b = t;
}
// A standard function to heapify at given idx
// This function also updates position of nodes when they are swapped.
// Position is needed for decreaseKey()
void minHeapify(struct MinHeap* minHeap, int idx)
{
int smallest, left, right;
smallest = idx;
left = 2 * idx + 1;
right = 2 * idx + 2;
if (left < minHeap->size &&
minHeap->array[left]->dist < minHeap->array[smallest]->dist )
smallest = left;
if (right < minHeap->size &&
minHeap->array[right]->dist < minHeap->array[smallest]->dist )
smallest = right;
if (smallest != idx)
{
// The nodes to be swapped in min heap
MinHeapNode *smallestNode = minHeap->array[smallest];
MinHeapNode *idxNode = minHeap->array[idx];
// Swap positions
minHeap->pos[smallestNode->v] = idx;
minHeap->pos[idxNode->v] = smallest;
// Swap nodes
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
minHeapify(minHeap, smallest);
}
}
// A utility function to check if the given minHeap is ampty or not
int isEmpty(struct MinHeap* minHeap)
{
return minHeap->size == 0;
}
// Standard function to extract minimum node from heap
struct MinHeapNode* extractMin(struct MinHeap* minHeap)
{
if (isEmpty(minHeap))
return NULL;
// Store the root node
struct MinHeapNode* root = minHeap->array[0];
// Replace root node with last node
struct MinHeapNode* lastNode = minHeap->array[minHeap->size - 1];
minHeap->array[0] = lastNode;
// Update position of last node
minHeap->pos[root->v] = minHeap->size-1;
minHeap->pos[lastNode->v] = 0;
// Reduce heap size and heapify root
--minHeap->size;
minHeapify(minHeap, 0);
return root;
}
// Function to decreasy dist value of a given vertex v. This function
// uses pos[] of min heap to get the current index of node in min heap
void decreaseKey(struct MinHeap* minHeap, int v, int dist)
{
// Get the index of v in heap array
int i = minHeap->pos[v];
// Get the node and update its dist value
minHeap->array[i]->dist = dist;
// Travel up while the complete tree is not hepified.
// This is a O(Logn) loop
while (i && minHeap->array[i]->dist < minHeap->array[(i - 1) / 2]->dist)
{
// Swap this node with its parent
minHeap->pos[minHeap->array[i]->v] = (i-1)/2;
minHeap->pos[minHeap->array[(i-1)/2]->v] = i;
swapMinHeapNode(&minHeap->array[i], &minHeap->array[(i - 1) / 2]);
// move to parent index
i = (i - 1) / 2;
}
}
// A utility function to check if a given vertex
// 'v' is in min heap or not
bool isInMinHeap(struct MinHeap *minHeap, int v)
{
if (minHeap->pos[v] < minHeap->size)
return true;
return false;
}
// The main function that calulates distances of shortest paths from src to all
// vertices. It is a O(ELogV) function
void dijkstra(struct Graph* graph, int src)
{
int V = graph->V;// Get the number of vertices in graph
int dist[V]; // dist values used to pick minimum weight edge in cut
// minHeap represents set E
struct MinHeap* minHeap = createMinHeap(V);
// Initialize min heap with all vertices. dist value of all vertices
for (int v = 0; v < V; ++v)
{
dist[v] = INT_MAX;
minHeap->array[v] = newMinHeapNode(v, dist[v]);
minHeap->pos[v] = v;
}
// Make dist value of src vertex as 0 so that it is extracted first
minHeap->array[src] = newMinHeapNode(src, dist[src]);
minHeap->pos[src] = src;
dist[src] = 0;
decreaseKey(minHeap, src, dist[src]);
// Initially size of min heap is equal to V
minHeap->size = V;
// In the followin loop, min heap contains all nodes
// whose shortest distance is not yet finalized.
while (!isEmpty(minHeap))
{
// Extract the vertex with minimum distance value
struct MinHeapNode* minHeapNode = extractMin(minHeap);
int u = minHeapNode->v; // Store the extracted vertex number
// Traverse through all adjacent vertices of u (the extracted
// vertex) and update their distance values
struct AdjListNode* pCrawl = graph->array[u].head;
while (pCrawl != NULL)
{
int v = pCrawl->dest;
// If shortest distance to v is not finalized yet, and distance to v
// through u is less than its previously calculated distance
if (isInMinHeap(minHeap, v) && dist[u] != INT_MAX &&
pCrawl->weight + dist[u] < dist[v])
{
dist[v] = dist[u] + pCrawl->weight;
// update distance value in min heap also
decreaseKey(minHeap, v, dist[v]);
}
pCrawl = pCrawl->next;
}
}
free(minHeap->pos);
for (int i=0;i<minHeap->size;i++) {
free(minHeap->array[i]);
}
free(minHeap->array);
free(minHeap);
}
// Driver program to test above functions
int main()
{
// create the graph given in above fugure
int V = 10000,t=0;
while (t!=10) {
struct Graph* graph = createGraph(V);
for (int i=0; i<5000; i++) {
for(int j=5000;j<10000;j++){
addEdge(graph, 0, i, i);
addEdge(graph, i, j, i+j);
}
}
dijkstra(graph, 0);
free(graph->array);
free(graph);
t++;
}
return 0;
}
You have these three lines at the end of your main:
free(graph->array);
free(graph);
t++;
You need to free the elements of the array (the adjacency lists) before freeing the array. Add this loop before the three lines:
for(int d=0; d<graph->V; d++)
{
AdjListNode *p1=graph->array[d].head, *p2;
while(p1)
{
p2=p1;
p1=p1->next;
free(p2);
}
}

Initialization and usage of a graph

I'm trying to implement a graph to store a list of data from a text file such as the following:
0,1 (node 0 links to 1)
0,2 (node 0 links to 2)
1,2 (node 1 links to 2)
2,1 (node 2 links to 1)
Anyways I come across trouble when it comes down to defining the structures. I'm torn between using a matrix or adjacent lists, but I think I will go with lists, I am just not sure how to define the structures. Should I use variable sized arrays, linked lists or something else? Which way would be the easiest?
struct grph{
};
struct node{
//ID of the node
int id;
};
Second, how do I store the data into this graph, this is where I come across the most trouble. Essentially, I thought it would be easy like linked lists where you just keep adding a node to the end. The difference here is that each node can point to many different nodes or to none at all. How do I link the graph structure with all the linked node structures?
When using linked lists for example, how would I store what node 0 connects to in the example above? I understand you use a matrix or list/array, but I'm seriously getting confused because of the lack of examples of such implementations in C. Any examples I found just made it much worse then I was before.
This is just an example:
struct node{
int id;
struct node **out;
int num_out;
/* optional: if you want doubly links */
struct node **in;
int num_in;
};
/* quick access to a node given an id */
struct node *node_list;
/* connect 'from' to 'to' */
void link(struct node *graph, int from, int to) {
struct node *nfrom = &node_list[from],
*nto = &node_list[to];
nfrom->num_out++;
nfrom->out = realloc(nfrom->out,
sizeof(struct node*) * nfrom->num_out);
nfrom->out[num_out-1] = nto;
/* also do similar to nto->in if you want doubly links */
}
In answer to your first question: adjacency matrix vs adjacency lists? If you expect your graph to be dense, i.e. most nodes are adjacent with most other nodes, then go for the matrix as most operations are much easier on matrices. If you really need a transitive closure, then matrices are probably better also, as these tend to be dense. Otherwise adjacency lists are faster and smaller.
A graph would look as follows:
typedef struct node * node_p;
typedef struct edge * edge_p;
typedef struct edge
{ node_p source, target;
/* Add any data in the edges */
} edge;
typedef struct node
{ edge_p * pred, * succ;
node_p next;
/* Add any data in the nodes */
} node;
typedef struct graph
{ node_p N;
} graph;
The N field of graph would start a linked list of the nodes of the graph using the next field of node to link the list. The pred and succ can be arrays allocated using malloc and realloc for the successor and predecessor edges in the graph (arrays of pointers to edges and NULL terminated). Even though keeping both successor and predecessors may seem redundant, you will find that most graph algorithms like to be able to walk both ways. The source and target field of an edge point back to the nodes. If you don't expect to store data in the edges, then you could let the pred and succ arrays point back directly to the nodes and forget about the edge type.
Don't try to use realloc on N in the graph because all the addresses of the nodes may change and these are heavily used in the remainder of the graph.
P.S: Personally I prefer circular linked lists over NULL ended linked lists, because the code for most, if not all, operations are much simpler. In that case graph would contain a (dummy) node instead of a pointer.
You could do something like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
void* pElements;
size_t ElementSize;
size_t Count; // how many elements exist
size_t TotalCount; // for how many elements space allocated
} tArray;
void ArrayInit(tArray* pArray, size_t ElementSize)
{
pArray->pElements = NULL;
pArray->ElementSize = ElementSize;
pArray->TotalCount = pArray->Count = 0;
}
void ArrayDestroy(tArray* pArray)
{
free(pArray->pElements);
ArrayInit(pArray, 0);
}
int ArrayGrowByOne(tArray* pArray)
{
if (pArray->Count == pArray->TotalCount) // used up all allocated space
{
size_t newTotalCount, newTotalSize;
void* p;
if (pArray->TotalCount == 0)
{
newTotalCount = 1;
}
else
{
newTotalCount = 2 * pArray->TotalCount; // double the allocated count
if (newTotalCount / 2 != pArray->TotalCount) // count overflow
return 0;
}
newTotalSize = newTotalCount * pArray->ElementSize;
if (newTotalSize / pArray->ElementSize != newTotalCount) // size overflow
return 0;
p = realloc(pArray->pElements, newTotalSize);
if (p == NULL) // out of memory
return 0;
pArray->pElements = p;
pArray->TotalCount = newTotalCount;
}
pArray->Count++;
return 1;
}
int ArrayInsertElement(tArray* pArray, size_t pos, void* pElement)
{
if (pos > pArray->Count) // bad position
return 0;
if (!ArrayGrowByOne(pArray)) // couldn't grow
return 0;
if (pos < pArray->Count - 1)
memmove((char*)pArray->pElements + (pos + 1) * pArray->ElementSize,
(char*)pArray->pElements + pos * pArray->ElementSize,
(pArray->Count - 1 - pos) * pArray->ElementSize);
memcpy((char*)pArray->pElements + pos * pArray->ElementSize,
pElement,
pArray->ElementSize);
return 1;
}
typedef struct
{
int Id;
int Data;
tArray LinksTo; // links from this node to other nodes (array of Id's)
tArray LinksFrom; // back links from other nodes to this node (array of Id's)
} tNode;
typedef struct
{
tArray Nodes;
} tGraph;
void GraphInit(tGraph* pGraph)
{
ArrayInit(&pGraph->Nodes, sizeof(tNode));
}
void GraphPrintNodes(tGraph* pGraph)
{
size_t i, j;
if (pGraph->Nodes.Count == 0)
{
printf("Empty graph.\n");
}
for (i = 0; i < pGraph->Nodes.Count; i++)
{
tNode* pNode = (tNode*)pGraph->Nodes.pElements + i;
printf("Node %d:\n Data: %d\n", pNode->Id, pNode->Data);
if (pNode->LinksTo.Count)
{
printf(" Links to:\n");
for (j = 0; j < pNode->LinksTo.Count; j++)
{
int* p = (int*)pNode->LinksTo.pElements + j;
printf(" Node %d\n", *p);
}
}
}
}
void GraphDestroy(tGraph* pGraph)
{
size_t i;
for (i = 0; i < pGraph->Nodes.Count; i++)
{
tNode* pNode = (tNode*)pGraph->Nodes.pElements + i;
ArrayDestroy(&pNode->LinksTo);
ArrayDestroy(&pNode->LinksFrom);
}
ArrayDestroy(&pGraph->Nodes);
}
int NodeIdComparator(const void* p1, const void* p2)
{
const tNode* pa = p1;
const tNode* pb = p2;
if (pa->Id < pb->Id)
return -1;
if (pa->Id > pb->Id)
return 1;
return 0;
}
int IntComparator(const void* p1, const void* p2)
{
const int* pa = p1;
const int* pb = p2;
if (*pa < *pb)
return -1;
if (*pa > *pb)
return 1;
return 0;
}
size_t GraphFindNodeIndexById(tGraph* pGraph, int Id)
{
tNode* pNode = bsearch(&Id,
pGraph->Nodes.pElements,
pGraph->Nodes.Count,
pGraph->Nodes.ElementSize,
&NodeIdComparator);
if (pNode == NULL)
return (size_t)-1;
return pNode - (tNode*)pGraph->Nodes.pElements;
}
int GraphInsertNode(tGraph* pGraph, int Id, int Data)
{
size_t idx = GraphFindNodeIndexById(pGraph, Id);
tNode node;
if (idx != (size_t)-1) // node with this Id already exist
return 0;
node.Id = Id;
node.Data = Data;
ArrayInit(&node.LinksTo, sizeof(int));
ArrayInit(&node.LinksFrom, sizeof(int));
if (!ArrayInsertElement(&pGraph->Nodes, pGraph->Nodes.Count, &node))
return 0;
qsort(pGraph->Nodes.pElements,
pGraph->Nodes.Count,
pGraph->Nodes.ElementSize,
&NodeIdComparator); // maintain order for binary search
return 1;
}
int GraphLinkNodes(tGraph* pGraph, int IdFrom, int IdTo)
{
size_t idxFrom = GraphFindNodeIndexById(pGraph, IdFrom);
size_t idxTo = GraphFindNodeIndexById(pGraph, IdTo);
tNode *pFrom, *pTo;
if (idxFrom == (size_t)-1 || idxTo == (size_t)-1) // one or both nodes don't exist
return 0;
pFrom = (tNode*)pGraph->Nodes.pElements + idxFrom;
pTo = (tNode*)pGraph->Nodes.pElements + idxTo;
// link IdFrom -> IdTo
if (bsearch(&IdTo,
pFrom->LinksTo.pElements,
pFrom->LinksTo.Count,
pFrom->LinksTo.ElementSize,
&IntComparator) == NULL) // IdFrom doesn't link to IdTo yet
{
if (!ArrayInsertElement(&pFrom->LinksTo, pFrom->LinksTo.Count, &IdTo))
return 0;
qsort(pFrom->LinksTo.pElements,
pFrom->LinksTo.Count,
pFrom->LinksTo.ElementSize,
&IntComparator); // maintain order for binary search
}
// back link IdFrom <- IdTo
if (bsearch(&IdFrom,
pTo->LinksFrom.pElements,
pTo->LinksFrom.Count,
pTo->LinksFrom.ElementSize,
&IntComparator) == NULL) // IdFrom doesn't link to IdTo yet
{
if (!ArrayInsertElement(&pTo->LinksFrom, pTo->LinksFrom.Count, &IdFrom))
return 0;
qsort(pTo->LinksFrom.pElements,
pTo->LinksFrom.Count,
pTo->LinksFrom.ElementSize,
&IntComparator); // maintain order for binary search
}
return 1;
}
int main(void)
{
tGraph g;
printf("\nCreating empty graph...\n");
GraphInit(&g);
GraphPrintNodes(&g);
printf("\nInserting nodes...\n");
GraphInsertNode(&g, 0, 0);
GraphInsertNode(&g, 1, 101);
GraphInsertNode(&g, 2, 202);
GraphPrintNodes(&g);
printf("\nLinking nodes...\n");
GraphLinkNodes(&g, 0, 1);
GraphLinkNodes(&g, 0, 2);
GraphLinkNodes(&g, 1, 2);
GraphLinkNodes(&g, 2, 1);
GraphPrintNodes(&g);
printf("\nDestroying graph...\n");
GraphDestroy(&g);
GraphPrintNodes(&g);
// repeat
printf("\nLet's repeat...\n");
printf("\nCreating empty graph...\n");
GraphInit(&g);
GraphPrintNodes(&g);
printf("\nInserting nodes...\n");
GraphInsertNode(&g, 1, 111);
GraphInsertNode(&g, 2, 222);
GraphInsertNode(&g, 3, 333);
GraphPrintNodes(&g);
printf("\nLinking nodes...\n");
GraphLinkNodes(&g, 1, 2);
GraphLinkNodes(&g, 2, 3);
GraphLinkNodes(&g, 3, 1);
GraphPrintNodes(&g);
printf("\nDestroying graph...\n");
GraphDestroy(&g);
GraphPrintNodes(&g);
return 0;
}
Output (ideone):
Creating empty graph...
Empty graph.
Inserting nodes...
Node 0:
Data: 0
Node 1:
Data: 101
Node 2:
Data: 202
Linking nodes...
Node 0:
Data: 0
Links to:
Node 1
Node 2
Node 1:
Data: 101
Links to:
Node 2
Node 2:
Data: 202
Links to:
Node 1
Destroying graph...
Empty graph.
Let's repeat...
Creating empty graph...
Empty graph.
Inserting nodes...
Node 1:
Data: 111
Node 2:
Data: 222
Node 3:
Data: 333
Linking nodes...
Node 1:
Data: 111
Links to:
Node 2
Node 2:
Data: 222
Links to:
Node 3
Node 3:
Data: 333
Links to:
Node 1
Destroying graph...
Empty graph.
It seems quite like my working, social networking...
You could define the node and links seperately. In c language, you could define as:
struct graph_node{
int id;
struct node_following *following;
struct graph_node *next_node;
}
struct node_following{
int id;
struct node_following *next_node;
}
For your example, the result is:
root -> node0 -> node1 -> node2
The content of root might be: id = -1; following=NULL; next_node= node0
The content of node0 might be: id = 0; next_node = node1; following point to a list of node_following as:
following -> {1, address of next node} -> {2, NULL}
The content of node1 might be: id = 1; next_node = node2; following point to a list of node_following as:
following -> {2, NULL}
The content of node2 might be: id = 2; next_node = NULL; following point to a list of node_following as:
following -> {1, NULL}
Essentially, it is a quesition on how to store a two-dimensional matrix. If the matrix is sparse, use the linked list. Otherwise, bitmap is a better solution.

Resources