Example of Disjktra Algorithm using Heap

NOTIFICATION: These examples are provided for educational purposes. The use of this code and/or information is under your own responsibility and risk. The information and/or code is given ‘as is’. I do not take responsibilities of how they are used.

Example of Disjktra algorithm using heap.

disjktra_heap.c:

/*
 * Program: 09
 * Author: Alejandro G. Carlstein
 * Description: Disjktra Algorithm using heap
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <limits.h>

#define MAX_EDGES 100001
#define MAX_VERTICES  500001
#define LEFT(i) ((i << 1) + 1)
#define RIGHT(i) ((i << 1) + 2)
#define DIV_BY_2(i) (i >> 1)
#define FALSE 0
#define TRUE 1

#define DBG_LV0 0
#define DBG_LV1 0
#define DBG_LV2 0
#define DBG_LV3 0

struct Edge{
  int startVertex;
  int endVertex;
  unsigned int length;
} edges[MAX_EDGES];

struct Vertex{
	unsigned int id;
	unsigned int weight;
	struct Vertex *predecessor;
	short visited;
} vertices[MAX_VERTICES];

struct AdjList{
	struct Vertex *vertexPointer;
	int edgeIndex;
	struct AdjList *next;
} *adjList[MAX_VERTICES], *headAdj, *newAdj;

void init(void);
void readStandardInput(void);
void printEdges(void);
void disjktraAlgorithm(void);
void initializeSingleSource(void);
void printVertices(void);
void buildAdjacentVertexList(void);
void insertAdjVerticesOf(int vertexIndex);
void insertAdjVertex(int vertexIndex, int adjVertexIndex, int edgeIndex);
void printAdjList(int vertexIndex);
void makePriorityQueue(int heapArray[], int *length);
void printArray(int array[], int length);
void buildMinHeap(int heapArray[], int length);
void minHeapify(int heapArray[], int index, int heapSize);
int heapExtractMin(int heapArray[], int *heapSize);
void exchange(int *a, int *b);
void addVertexToList(struct AdjList *vertexList, struct Vertex *vertex);
void relax(int startVertex, int endVertex, int edge);
void printRoute(void);
void debug(int debugLevel, char *fmt, ...);
void errorDoExit(char *fmt, ...);

int numVertices, numEdges;
int main(int argc, char *argv[]){

	init();
	disjktraAlgorithm();
	printVertices();
	return 0;
}

void init(void){
	debug(DBG_LV0, 'init()');
	readStandardInput();
}

void readStandardInput(void){
	debug(DBG_LV0, 'readStandardInput()');	

	scanf('%d %d', &numVertices, &numEdges);
	debug(DBG_LV1, '# of vertices: %d, # of edges: %d', numVertices, numEdges);
	printEdges();
}

void printEdges(void){
	debug(DBG_LV0, 'printEdges()');	

	int i;
	for(i = 0; i < numEdges; ++i){
		scanf('%d %d %d', &edges[i].startVertex, &edges[i].endVertex, &edges[i].length);
		debug(DBG_LV1, '[%d](%d <%d> %d)', i, edges[i].startVertex, edges[i].length, edges[i].endVertex);
	}
}

// Disjktra(G, w, s)	//s is source vertex - w is weight
void disjktraAlgorithm(void){
	debug(DBG_LV0, 'disjktraAlgorithm()');	

	// InitializeSingleSource(G, s);
	initializeSingleSource();

	//	S <- 0    // It will hold vertices
	struct AdjList *vertexList = NULL;

	//	Q <- V[G] // Make a priority Queue for the vertices
	int heapArray[numVertices];
	int heapLength = 0;
	makePriorityQueue(heapArray, &heapLength);

	//	while Q != 0
	while(heapLength > 0){	

		//		do u <- extractMin(Q)
		if (DBG_LV1) printArray(heapArray, heapLength);
		int vertexIndex = heapExtractMin(heapArray, &heapLength);
		debug(DBG_LV1, '[!]vertex[%d] Weight: %d\n', vertexIndex, vertices[vertexIndex].weight);
		if (DBG_LV1) printArray(heapArray, heapLength);		

		//S <- S U {u}
		addVertexToList(vertexList, &vertices[vertexIndex]);

		//		for each vertex v e Adj[u]
		struct AdjList *tempAdj;
		tempAdj = adjList[vertexIndex];
		while(tempAdj != NULL){
			//			do relax(u, v, w);
			relax(vertexIndex, tempAdj->vertexPointer->id, tempAdj->edgeIndex);
			tempAdj = tempAdj->next;
		}
		vertices[vertexIndex].visited = TRUE;
	}

}	

void initializeSingleSource(void){
	debug(DBG_LV0, 'initializeSingleSource()');	

	int i;
	for(i = 0; i < numVertices; ++i){
		vertices[i].id = i;
		vertices[i].weight = INT_MAX;
		vertices[i].predecessor = NULL;	// p[v] predecessor that is either another vertex or NULL
		vertices[i].visited = FALSE;
	}
	vertices[0].weight = 0;

	if (DBG_LV1) printVertices();

	buildAdjacentVertexList();	

	if (DBG_LV1){
		debug(DBG_LV1, '*List of all adj. vertices*');
		for (i = 0; i < numVertices; ++i)
			printAdjList(i);
	}

}

void printVertices(void){
	debug(DBG_LV0, 'printVertices()');  

	printf('[ ]');
	int i;
	for (i = 0; i < numVertices; ++i)
		printf('[%d]', i);

	if (DBG_LV1){
		printf('\n[i]');
		for (i = 0; i < numVertices; ++i)
			printf(' %d ' , vertices[i].id);
	}

	printf('\n[W]');
	for (i = 0; i < numVertices; ++i)
		if (vertices[i].weight == INT_MAX){
			printf(' ! ');
		}else{
			printf(' %d ' , vertices[i].weight);
		}

	if(DBG_LV1){
		printf('\n[*]');
		for (i = 0; i < numVertices; ++i)
			if (vertices[i].predecessor == NULL){
				printf(' N ');
			}else{
				printf(' %d ' , (int)vertices[i].predecessor->id);
			}
	}

	if(DBG_LV1){
		printf('\n[V]');
		for (i = 0; i < numVertices; ++i)
			if (vertices[i].visited == TRUE){
				printf(' Y ');
			}else{
				printf(' N ');
			}
	}

	printf('\n');
}

void buildAdjacentVertexList(void){
	debug(DBG_LV0, 'buildAdjacentVertexList()');

	int vertexIndex;
	for (vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex){
		insertAdjVerticesOf(vertexIndex);
	}
}

void insertAdjVerticesOf(int vertexIndex){
	debug(DBG_LV0, 'insertAdjVerticesOf(vertexIndex: %d)', vertexIndex);	

	debug(DBG_LV1, ' Searching for adjacent Vertices');
	int edgeIndex;
	for (edgeIndex = 0; edgeIndex < numEdges; ++edgeIndex){

		int startVertex = edges[edgeIndex].startVertex;
		int endVertex = edges[edgeIndex].endVertex;
		debug(DBG_LV1, '  Edge[%d](%d <%d> %d)', edgeIndex, startVertex, edges[edgeIndex].length, endVertex);

		debug(DBG_LV1, '  (startVertex (%d) == (%d) vertexIndex)?', startVertex, vertexIndex);
		if (startVertex == vertexIndex){
			debug(DBG_LV1, '   YES');
			insertAdjVertex(vertexIndex, endVertex, edgeIndex);
			insertAdjVertex(endVertex, vertexIndex, edgeIndex);
		}
	}
	if(DBG_LV1) printAdjList(vertexIndex);
}

void insertAdjVertex(int vertexIndex, int adjVertexIndex, int edgeIndex){

	struct AdjList *headAdj;
	headAdj = adjList[vertexIndex];	

	struct AdjList *newAdj = (struct AdjList *) malloc(sizeof(struct AdjList));
	newAdj->vertexPointer = &vertices[adjVertexIndex];
	newAdj->edgeIndex = edgeIndex;
	newAdj->next = NULL;

	if (headAdj == NULL){
		newAdj->next = adjList[vertexIndex];
		adjList[vertexIndex] = newAdj;
	}else{
		struct AdjList *currentAdj = adjList[vertexIndex];
		while (currentAdj->next != NULL)
			currentAdj = currentAdj->next;
		newAdj->next = currentAdj->next;
		currentAdj->next = newAdj;
	}
}

void printAdjList(int vertexIndex){
	debug(DBG_LV0, '**printAdjList(vertexIndex: %d)', vertexIndex);	

	debug(DBG_LV1, 'Adjacent Vertices of Vertex: %d', vertexIndex);

	struct AdjList *tempAdj;
	tempAdj = adjList[vertexIndex];	

	if (tempAdj == NULL){
		debug(DBG_LV1, ' tempAdj is empty');
	}else{		

		printf('[%d]', vertexIndex);
		int i = 0;
		while(tempAdj != NULL){
			printf('[%d]', i++);
			tempAdj = tempAdj->next;
		}

		printf('\n[i]');
		tempAdj = adjList[vertexIndex];
		while(tempAdj != NULL){
			printf(' %d ', tempAdj->vertexPointer->id);
			tempAdj = tempAdj->next;
		}

		printf('\n[W]');
		tempAdj = adjList[vertexIndex];
		while(tempAdj != NULL){
			if (tempAdj->vertexPointer->weight == INT_MAX){
				printf(' ! ');
			}else{
				printf(' %d ' , tempAdj->vertexPointer->weight);
			}
			tempAdj = tempAdj->next;
		}

		printf('\n[*]');
		tempAdj = adjList[vertexIndex];
		while(tempAdj != NULL){
			if (tempAdj->vertexPointer->predecessor == NULL){
				printf(' N ');
			}else{
				printf(' %d ' , tempAdj->vertexPointer->predecessor->id);
			}
			tempAdj = tempAdj->next;
		}

		printf('\n[V]');
		tempAdj = adjList[vertexIndex];
		while(tempAdj != NULL){
			if (tempAdj->vertexPointer->visited == TRUE){
				printf(' Y ');
			}else{
				printf(' N ');
			}
			tempAdj = tempAdj->next;
		}

		printf('\n');
	}
}

void makePriorityQueue(int heapArray[], int *length){
	debug(DBG_LV0, 'makePriorityQueue(length: %d)', *length);

	int i;
	for (i = 0; i < numVertices; ++i)
		heapArray[i] = i;

	*length = numVertices;
	if (DBG_LV1) printArray(heapArray, *length);
	buildMinHeap(heapArray, *length);
	if (DBG_LV1) printArray(heapArray, *length);
	if (DBG_LV1) printVertices();
}

void printArray(int array[], int length){
	debug(DBG_LV0, 'printArray(length: %d)', length);

	int i;
	for (i = 0; i < length; ++i)
		printf('[%d]', i);

	printf('\n');
	for (i = 0; i < length; ++i)
		printf(' %d ', array[i]);
	printf('\n');
}

void buildMinHeap(int heapArray[], int length){
	debug(DBG_LV0, 'buildMinHeap(length: %d)', length);

	int heapSize = length;

	int index;
	for (index = DIV_BY_2(length); index > -1; --index)
		minHeapify(heapArray, index, heapSize);
}

void minHeapify(int heapArray[], int index, int heapSize){
	debug(DBG_LV2, 'minHeapify(index: %d, heapSize: %d)', index, heapSize);

	int smallestIndex = index;
	int leftIndex = LEFT(index);
	int rightIndex = RIGHT(index);
	debug(DBG_LV1, '-SmallestIndex: %d, leftIndex: %d, rightIndex: %d', smallestIndex, leftIndex, rightIndex);

	if (leftIndex <= heapSize && rightIndex <= heapSize){

		unsigned int indexValue = vertices[heapArray[index]].weight;
		debug(DBG_LV1,
					'INDEX: vertices[heapArray[%d]: %d].id: %d, .weight: %d',
					index, heapArray[index], vertices[heapArray[index]].id,
					indexValue);

		unsigned int leftValue = vertices[heapArray[leftIndex]].weight;
		debug(DBG_LV1,
					'LEFT VALUE: vertices[heapArray[%d]: %d].id: %d, .weight: %d',
					leftIndex, heapArray[leftIndex], vertices[heapArray[leftIndex]].id,
					leftValue);

		if ((leftIndex < heapSize) && (leftValue < indexValue))
			smallestIndex = leftIndex;

		debug(DBG_LV1, 'smallestIndex: %d', smallestIndex);

		unsigned int rightValue = vertices[heapArray[rightIndex]].weight;

		debug(DBG_LV1,
					'LEFT VALUE: vertices[heapArray[%d]: %d].id: %d, .weight: %d',
					rightIndex, heapArray[rightIndex], vertices[heapArray[rightIndex]].id,
					rightValue);

		if ((rightIndex < heapSize) && (rightValue < indexValue))
			smallestIndex = rightIndex;

		debug(DBG_LV1, 'smallestIndex: %d', smallestIndex);

		if (smallestIndex != index){
			exchange(&heapArray[index], &heapArray[smallestIndex]);
			minHeapify(heapArray, smallestIndex, heapSize);
		}
	}
}

int heapExtractMin(int heapArray[], int *heapSize){
	debug(DBG_LV0, 'heapExtractMin(heapSize: %d)', *heapSize);

	if (*heapSize < 1)
		errorDoExit('Heap Underflow');

	buildMinHeap(heapArray, *heapSize);

	int min = heapArray[0];
	--*heapSize;
	heapArray[0] = heapArray[*heapSize];
	minHeapify(heapArray, 1, *heapSize);

	return min;
}

void exchange(int *a, int *b){
	debug(DBG_LV3, 'exchange(a: %d, b: %d)', *a, *b);

		int temp;
		temp = *a;
		*a = *b;
		*b = temp;
}

void addVertexToList(struct AdjList *vertexList, struct Vertex *vertex){
	debug(DBG_LV0, 'addVertexToList()');	

	struct AdjList *newAdj = (struct AdjList *) malloc(sizeof(struct AdjList));
	newAdj->vertexPointer = vertex;
	if (vertexList == NULL){
		newAdj->next = vertexList;
		vertexList = newAdj;
	}else{
		struct AdjList *currentAdj = vertexList;
		while (currentAdj->next != NULL)
			currentAdj = currentAdj->next;
		newAdj->next = currentAdj->next;
		currentAdj->next = newAdj;
	}
}

void relax(int startVertex, int endVertex, int edgeIndex){
	debug(DBG_LV0, 'relax(startVertex: %d, endVerted: %d, edgeIndex: %d)', startVertex, endVertex, edgeIndex);	

	unsigned int weight = vertices[startVertex].weight + edges[edgeIndex].length;

	debug (DBG_LV1, 'vertices[%d].weight(%d) > (%d)weight', endVertex, vertices[endVertex].weight, weight);
	if (vertices[endVertex].weight > weight){
		vertices[endVertex].weight = weight;
		vertices[endVertex].predecessor = &vertices[startVertex];
	}
}	

void debug(int debugLevel, char *fmt, ...){
	if (debugLevel){
		va_list argp;
		fprintf(stdout, '[DBG] ');
		va_start(argp, fmt);
		vfprintf(stdout, fmt, argp);
		va_end(argp);
		fprintf(stdout, '\n');
	}
}

void errorDoExit(char *fmt, ...){
	va_list argp;
	fprintf(stderr, '[Error] ');
	va_start(argp, fmt);
	vfprintf(stderr, fmt, argp);
	va_end(argp);
	if (errno){
		fprintf(stderr, '=> %s\n', strerror(errno));
	}else{
		fprintf(stderr, '\n');
	}
	exit(1);
}

input.txt:

8 11
0 1 1
4 5 1
1 5 2
2 5 2
5 6 2
0 3 2
3 4 3
5 7 3
4 2 4
4 6 4
1 2 5

If you encounter any problems or errors, please let me know by providing an example of the code, input, output, and an explanation. Thanks.

Share
Leave a comment

Example of Kurskay’s Algorithm using Disjoint Sets and Heap

NOTIFICATION: These examples are provided for educational purposes. The use of this code and/or information is under your own responsibility and risk. The information and/or code is given ‘as is’. I do not take responsibilities of how they are used.

Example of Kurskay’s algorithm using disjoint sets and heap.

kurskay_djoinset_heap.c:

/*
 * Program: 08
 * Author: Alejandro G. Carlstein
 * Description: Applying Kurskay's Algorithm using Disjoint Sets
 */

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <malloc.h>

#define MAX_EDGES 100001
#define MAX_VERTICES  500001
#define MAX_HEAP 100001
#define LEFT(i) ((i << 1) + 1)
#define RIGHT(i) ((i << 1) + 2)
#define PARENT(i) (((i + 1) >> 1) - 1)
#define DIV_BY_2(i) (i >> 1)
#define ROOT_INDEX 0

#define DBG_LV0 0
#define DBG_LV1 0
#define DBG_LV2 0
#define DBG_LV3 0

struct Vertex{
	int id;
	int rank;
	struct Vertex *parent;
};

struct Edge{
  struct Vertex *startVertex;
  struct Vertex *endVertex;
  int length;
};

struct Edge edges[MAX_EDGES];
struct Vertex vertices[MAX_VERTICES];
int heap[MAX_EDGES];

void scanEdges(void);
void debug(const char *message, int isDebugging);
void printEdges(struct Edge edges[], int length);
void initHeap(void);
int *mstKruskal(int *numEdges);
void printVertices(struct Vertex vertices[]);
void heapSort(int array[], int length);
void buildMinHeap(int array[], int heapSize);
void minHeapify(int array[], int index, int heapSize);
void exchange(int *a, int *b);
void printArray(int array[], int length);
void makeSet(struct Vertex *vertex);
struct Vertex* findSet(struct Vertex *vertex);
void unionTrees(struct Vertex *vertexX, struct Vertex *vertexY);
void link(struct Vertex *vertexX, struct Vertex *vertexY);
void printEdgesUsingHeapArray(int heapArray[], int length);
void printWeightOfTree(int heapArray[], int length);

int numVertices;
int numEdges;

int main(int argc, char* argv[]){

	scanEdges();
	initHeap();
	int length = numEdges;
 	int *arrayHeapEdges;
 	arrayHeapEdges = mstKruskal(&length);

 	if (DBG_LV1) printArray(arrayHeapEdges, length);

 	if(DBG_LV1) printVertices(vertices);

	if (DBG_LV1) printEdgesUsingHeapArray(arrayHeapEdges, length);		

	printWeightOfTree(arrayHeapEdges, length);

	free(arrayHeapEdges);

	return 0;

}

void scanEdges(void){
	debug('scanEdges()', DBG_LV0);

	scanf('%d %d', &numVertices, &numEdges);

	if (DBG_LV1) printf('numVertices: %d, numEdges: %d\n', numVertices, numEdges);

	int i;
	int startVertexId = -1;
	int endVertexId = -1;
	for (i = 0;
			 scanf('%d %d %d', &startVertexId, &endVertexId, &edges[i].length) == 1 ||
			 			 i < numEdges;
			 ++i){

		if (DBG_LV2)
			printf('startVertexId: %d, endVertexId: %d\n', startVertexId, endVertexId);

		if (startVertexId >= numVertices ||
				endVertexId >= numVertices){
			fprintf(stderr, 'Error: Vertex id is outside the maximum range of vertices\n');
			exit(1);
		}

		vertices[startVertexId].id = startVertexId;
		edges[i].startVertex = &vertices[startVertexId];

		vertices[endVertexId].id = endVertexId;
		edges[i].endVertex = &vertices[endVertexId];

		if(DBG_LV2)
			printf('edges[%d].startVertex->id: %d, edges[%d].endVertex->id: %d\n',
						 i, edges[i].startVertex->id, i, edges[i].endVertex->id);

	}

	if (DBG_LV1)
		printEdges(edges, numEdges);

}

void debug(const char *message, int isDebugging){
	if (isDebugging) printf('%s\n', message);
}

void printEdges(struct Edge edges[], int length){
	debug('printEdges()', DBG_LV0);

	printf('Edges: \n');
	int i;
	for (i = 0; i < length; ++i)
		printf('%d(%d <%d> %d) ',
					 i, edges[i].startVertex->id, edges[i].length, edges[i].endVertex->id);

		printf('\n');
}

void initHeap(void){
	debug('initHeap()', DBG_LV0);

	int i;

	for (i = 0; i < numEdges; ++i)
		heap[i] = i;
}

int *mstKruskal(int *numEdges){
	debug('mstKruskal()', DBG_LV0);	

	// A <- 0
	int *arrayEdgesIndex = (int*) malloc(*numEdges * sizeof(int));

	int vertexIndex;
	for (vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
		makeSet(&vertices[vertexIndex]);

	if (DBG_LV1) printVertices(vertices);

	// Sort edges into nondecreasing order by weight
	heapSort(heap, *numEdges);

	int index = 0;
	int edgeIndex;
	for (edgeIndex = 0; edgeIndex < *numEdges; ++edgeIndex){

		if (DBG_LV2)
			printf('V: %d\n', (int)findSet(edges[heap[edgeIndex]].startVertex));

		if ((int)findSet(edges[heap[edgeIndex]].startVertex) !=
				(int)findSet(edges[heap[edgeIndex]].endVertex)  ){

			if (DBG_LV2)
				printf('findset(edges[%d]) = findset(edges[%d])\n',
							 heap[edgeIndex], heap[edgeIndex]);

			// A <- A U {(u,v)}
			arrayEdgesIndex[index++] = heap[edgeIndex];	

			unionTrees(edges[heap[edgeIndex]].startVertex,
								 edges[heap[edgeIndex]].endVertex);
		}

	}

	*numEdges = index;

	if (DBG_LV1) printArray(arrayEdgesIndex, index);

	return (arrayEdgesIndex);
}

void printVertices(struct Vertex vertices[]){
	debug('printVertices()', DBG_LV0);

	int i;
	for (i = 0; i < numVertices; ++i)
		printf('(%d)[%d] Id: %d, Rank: %d, *Parent:%d \n',
					 (int)&vertices[i], i, vertices[i].id, vertices[i].rank, (int)vertices[i].parent);

	printf('\n');
}

void heapSort(int array[], int length){
	if (DBG_LV0) printf('heapSort(length: %d)\n', length);

	buildMinHeap(array, length);

	int i;
	int	heap_size = length;
	for (i = length - 1 ; i >= 0; --i){
		exchange(&array[0], &array[i]);
		heap_size--;
		minHeapify(array, 0, heap_size);
	}

}

void buildMinHeap(int array[], int heapSize){
	debug('buildMinHeap', DBG_LV0);

	int index;
	for (index = DIV_BY_2(heapSize); index >= ROOT_INDEX; --index)
		minHeapify(array, index, heapSize);
}

void minHeapify(int array[], int index, int heapSize){
	debug('minHeapify()', DBG_LV0);

	int left, right, smallest;

	smallest = index;
	left = LEFT(index);
	right = RIGHT(index);	

	if (left < heapSize &&
		  edges[array[left]].length > edges[array[index]].length)
		smallest = left;	

	if (right < heapSize &&
		  edges[array[right]].length > edges[array[smallest]].length)
		smallest = right;

	if (smallest != index){
		exchange(&array[index], &array[smallest]);
		minHeapify(array, smallest, heapSize);
	}

}

void exchange(int *a, int *b){
	debug('exchange()', DBG_LV3);

	int temp;
	temp = *a;
	*a = *b;
	*b = temp;
}

void makeSet(struct Vertex *vertex){
	debug('makeSet()', DBG_LV0);

	vertex->parent = vertex;
	vertex->rank = 0;
}

struct Vertex* findSet(struct Vertex *vertex){
	debug('findSet()', DBG_LV0);

	if (vertex == NULL)
		debug('Vertex is NULL', DBG_LV1);

	if (vertex != vertex->parent){
		vertex->parent = findSet(vertex->parent);
	}	

	return (vertex->parent);
}

void unionTrees(struct Vertex *vertexX, struct Vertex *vertexY){
	debug('unionTrees()', DBG_LV0);

	link(findSet(vertexX), findSet(vertexY));
}

void link(struct Vertex *vertexX, struct Vertex *vertexY){
	debug('link()', DBG_LV0);

	if (vertexX->rank > vertexY->rank){
		vertexY->parent = vertexX;
	}else{
		vertexX->parent = vertexY;
		if (vertexX->rank == vertexY->rank)
			++vertexY->rank;
	}

}

void printArray(int array[], int length){
	debug('printArray()', DBG_LV0);

	int i;

	for (i = 0; i < length; ++i)
		printf('[%d]', i);

	printf('\n');

	for (i = 0; i < length; ++i)
		printf(' %d ', array[i]);

	if (DBG_LV1) printf('\n\n');
}

void printEdgesUsingHeapArray(int heapArray[], int length){
	debug('printEdgesUsingHeapArray()', DBG_LV0);

	int i;
	for (i = 0; i < length; ++i)
		printf('%d-%d(%d) ',
					 edges[heapArray[i]].startVertex->id, edges[heapArray[i]].endVertex->id, (i + 1));
}

void printWeightOfTree(int heapArray[], int length){
	debug('printWeightOfTree()', DBG_LV0);

	int result = 0;
	int i;
	for (i = 0; i < length; ++i)
		result += edges[heapArray[i]].length;

	printf('%d\n', result);

}

input.txt:

4 7

0 1 5

0 2 4

1 3 3

2 3 2

3 0 1

2 1 10

0 3 20

If you encounter any problems or errors, please let me know by providing an example of the code, input, output, and an explanation. Thanks.

Share
Leave a comment

Example of Huffman Algorithm by using Heap

Example of Huffman algorithm by using heap.

NOTIFICATION: These examples are provided for educational purposes. Using this code is under your own responsibility and risk. The code is given ‘as is’. I do not take responsibilities of how they are used.

huffman.c:

/* 
 * Program: Huffman using heap
 * Author: Alejandro G. Carlstein
 */

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define MAX_CODE 1000000
#define MAX_LETTERS 4
#define MAX_HEAP 10
#define LEFT(i) ((i << 1) + 1)
#define RIGHT(i) ((i << 1) + 2)
#define PARENT(i) (((i + 1) >> 1) - 1)
#define DIV_BY_2(i) (i >> 1)
#define DBG_LV0 1
#define DBG_LV1 1
#define DBG_LV2 1
#define DBG_LV3 0
#define LETTER_A 65
#define DIR_LEFT '0'
#define DIR_RIGHT '1'

#define ROOT_INDEX 0

struct Data{
  int letter;
  int frequency;
  int left;
  int right;
  int parent;
}Data;

struct Data data[MAX_LETTERS];
int code[MAX_CODE][MAX_LETTERS];
int heap[MAX_HEAP];

void readInputLetters(void);
void readInputCode(void);
void printCodes(int *codes, int numCodes);
void printStructArray(struct Data array[], int length);
int huffman(void);
void buildMinHeap(int array[], int heapSize);
void minHeapify(int array[], int index, int heapSize);
int heapMin(int array[]);
int heapExtractMin(int array[], int *length);
void insertMinHeap(int array[], int value, int *length);
void exchange(int *a, int *b);
void printArray(int array[], int length);
int isLeft(struct Data array[], int indexLeft, int indexRight);
void test1();
void test2();

int num_letters;
int numCodes = 0;

int main(int argc, char* argv[]){

	readInputLetters();		

	readInputCode();

	if (DBG_LV3) printStructArray(data, num_letters);

	int i;
	for (i = 0; i < num_letters; ++i)
		heap[i] = i;

  printf('ROOT(huffman): %d \n', huffman());

	if (DBG_LV1) printStructArray(data, num_letters);

  //decodeMessage(data, num_letters, &code[0][0], numCodes);

	if (DBG_LV2) printf('\n');

	return 0;

}

void readInputLetters(void){
	if (DBG_LV0) printf('\nreadInputLetters()\n');

  for (num_letters = 0; num_letters < MAX_LETTERS; ++num_letters){       
    scanf('%d', &data[num_letters].frequency);
    data[num_letters].letter = LETTER_A + num_letters;
    data[num_letters].left = -1;
    data[num_letters].right = -1;
		data[num_letters].parent = -1;

    heap[num_letters] = -1;
  }

}

void readInputCode(void){
	if (DBG_LV0) printf('\nreadInputCode()\n');

	int c;
  int indexCode = 0;

  numCodes = 0;

  while ((c = getchar()) != EOF){

    if (c != ' ' && c != '\n'){
      if (DBG_LV3) printf('[%d][%d]%c{%d}\n', numCodes, indexCode, c, c);
      code[numCodes][indexCode] = (int)c;
      ++indexCode;
    }

    if (c == '\n'){
      code[numCodes][indexCode] = -1;
      if (DBG_LV3) printf('{{%d}}\n', code[numCodes][indexCode]);
      ++numCodes;
      indexCode = 0;

    }
  }

	if (DBG_LV3){
	  printf('CODES: \n');
	  printCodes(&code[0][0], numCodes);

  }

}

void printCodes(int *codes, int numCodes){
  if (DBG_LV2) printf('printCodes(numCodes: %d)\n', numCodes);

  int indexCode, index;
	int indexArray;

  for (indexCode = 0; indexCode < numCodes; ++indexCode){

		indexArray = indexCode * sizeof(int);

    for (index = 0; codes[indexArray + index] > -1 ; ++index){

      printf('[%d][%d]: %c(%d) \n', 
             indexArray, index, 
             codes[indexArray + index], codes[indexArray + index]);    

    }

    printf('\n');

  }

}

void printStructArray(struct Data array[], int length){
  if (DBG_LV0) printf('printStructArray()\n');

  int i;
  for (i = 0; i < length; ++i)
	  printf('[%d]%c - %d (L:%d, R:%d, P:%d) \n',
	         i, data[i].letter, data[i].frequency, data[i].left, data[i].right, data[i].parent);
}

int huffman(void){
	if (DBG_LV0) printf('\nHUFFMAN()\n');

	int length = num_letters;
	int i;
	int left;
	int right;
	int parent;
	int n = length;

	length++;

	printf('length: %d\n\n', length);

	if (DBG_LV1) printArray(heap, num_letters);

	for (i = 0; i < n - 1; ++i){

		left = heapExtractMin(heap, &length);

		printf('length: %d\n\n', length);

		right = heapExtractMin(heap, &length);

		parent = left + right;

		data[left].parent = parent;
		data[right].parent = parent;

		printf('length: %d\n\n', length);

		if (DBG_LV2){
			printf('left: %d, ', left);				
			printf('right: %d, ', right);
			printf('parent: %d\n', parent);
			printArray(heap, length);		
		}

		insertMinHeap(heap, parent, &length);

		printf('length: %d\n\n', length);
		//--*length;

	}

	if (DBG_LV1) printArray(heap, num_letters);

	return heapExtractMin(heap, &length);
}

void buildMinHeap(int array[], int heapSize){

	int index;

	for (index = DIV_BY_2(heapSize); index >= ROOT_INDEX; --index){

		minHeapify(array, index, heapSize);

	}

}

void minHeapify(int array[], int index, int heapSize){

	int left, right, smallest;

	smallest = index;
	left = LEFT(index);
	right = RIGHT(index);	

	// Find smallest value
	if (left < heapSize && array[left] < array[index])
		smallest = left;	

	if (right < heapSize && array[right] < array[smallest]) 
		smallest = right;

	if (smallest != index){

		// Exchange 
		exchange(&array[index], &array[smallest]);

		// Rebuild heap region		
		minHeapify(array, smallest, heapSize);	

	}

}

int heapMin(int array[]){
	return array[ROOT_INDEX];
}

int heapExtractMin(int array[], int *length){
	if (DBG_LV0) printf('heapExtractMin()\n');

	if (length < 0){
		printf('[X] Error: heap overflow!\n');
		return -1;
	}

	--*length;

	int heapSize = *length;

	int min = array[ROOT_INDEX];

	--heapSize;

	printf('exchange: array[%d]: %d, array[%d]:%d \n',
				 ROOT_INDEX, array[ROOT_INDEX],
				 heapSize, array[heapSize]);

	exchange(&array[ROOT_INDEX], &array[heapSize]);

	--heapSize;

	minHeapify(array, ROOT_INDEX, heapSize);

	return min;
}

void insertMinHeap(int array[], int value, int *length){

	if (DBG_LV0) printf('insertMinHeap(value: %d, length: %d)\n',
											value, *length);

	int heapSize = *length;

	++*length;

	array[heapSize] = INT_MAX;

	if (value > array[heapSize]){
		printf('[X] Error: new value is bigger than biggest element!\n');
	}else{

		array[heapSize] = value;

		if (DBG_LV2) printArray(array, *length);

		while (heapSize > ROOT_INDEX && 
					 array[PARENT(heapSize)] > array[heapSize]){

			exchange(&array[heapSize], &array[PARENT(heapSize)]);

			heapSize = PARENT(heapSize);

		}

	}

}

void exchange(int *a, int *b){
		if (DBG_LV3) printf('exchange()\n');

		int temp;
		temp = *a;
		*a = *b;
		*b = temp;
}

void printArray(int array[], int length){
	if (DBG_LV0) printf('printArray()\n');

	int i;

	for (i = 0; i < length; ++i)
		printf('[%d]', i);

	printf('\n');

	for (i = 0; i < length; ++i)
		printf(' %d ', array[i]);

	if (DBG_LV1) printf('\n\n');
}

int isLeft(struct Data array[], int indexLeft, int indexRight){
	if (DBG_LV0) printf('isLeft()\n');

	if (array[indexLeft].frequency == array[indexRight].frequency){

		 	if (array[indexLeft].letter < array[indexRight].letter){
		 		return DIR_LEFT;
		 	}else{
		 		return DIR_RIGHT;
		 	}

	}else if (array[indexLeft].frequency < array[indexRight].frequency){
		return DIR_LEFT;	 	
	}else{
		return DIR_RIGHT;
	} 

}

void test1(){
	if (DBG_LV1) printf('test1()\n');

	int i, length = 5;

	if(DBG_LV1)	printf('BUILD HEAP ARRAY:\n');
	for(i = 0; i < length; ++i){
		heap[i] = i * 2;
		printf('heap[%d]: %d \n', i, heap[i]);
	}
	heap[4] = 1;

	buildMinHeap(heap, length);

	printArray(heap, length);

	insertMinHeap(heap, 3, &length);

	printArray(heap, length);
}

void test2(){

	int heapLen = num_letters;

	printf('heapLen: %d\n', heapLen);

	printArray(heap, heapLen);

	int result1, result2;

	printf('TEST HEAPEXTRACTMIN:\n');
	result1 = heapExtractMin(heap, &heapLen);
  printf('result1: %d\n', result1);
	printArray(heap, heapLen);

	printf('heapLen: %d\n', heapLen);

	result2 = heapExtractMin(heap, &heapLen);
  printf('result2: %d\n', result2);
	printArray(heap, heapLen);

	printf('heapLen: %d\n', heapLen);

}

input.txt:

1 
2 
3 
4 
1 0 0 
1 0 1 
1 1 
0

If you encounter any problems or errors, please let me know by providing an example of the code, input, output, and an explanation. Thanks.

Share
Leave a comment

Example of Ferry Loading Algorithm

Example of Ferry Loading algorithm.

NOTIFICATION: These examples are provided for educational purposes. Using this code is under your own responsibility and risk. The code is given ‘as is’. I do not take responsibilities of how they are used.

ferry_loading.c:

/**
 * Ferry Loading Algorithm
 * @author: Alejandro G. Carlstein R. M. 
 */
#include <stdio.h>

/* Macros Functions */
#define max(a,b) \
           ({ typeof (a) _a = (a); \
              typeof (b) _b = (b); \
            _a > _b ? _a : _b; })

/* Debugging flags */
#define DBG_LV1 0
#define DBG_LV2 1
#define DBG_LV3 0

/* Constants */
#define MAX_NUM_CAR 100
#define MAX_FERRY_LEN 100

enum{ UNKNOWN = -1, LEFT = 0, RIGHT = 1,
};

/* Our dynamic programming table element.  We have the value
 * that we can store, and also a way to remember what we selected.
 */
typedef struct{
  int length;
  int prev_row;
  int prev_col;
} Table;

int cars[MAX_NUM_CAR];
int side[MAX_NUM_CAR];
int i, j;
int ferry_len;
int total_cars;

// [ROW] [COLUMN]
Table ferry[MAX_FERRY_LEN][MAX_FERRY_LEN];

/*
 *
 */
int main(int argc, char *argv[]){

  /* Read the length of the ferry */
  scanf('%d', &ferry_len);

  // Read length of each car and set side to UNKNOWN since
  // we haven't decided yet where they will go
  cars[0] = 0;
  side[0] = UNKNOWN;
  for (i = 1; scanf('%d', &cars[i]) == 1; ++i){
    side[i] = UNKNOWN;
  };
  total_cars = i;

  // Initialize the first row and the first column
  for (i = 0; i <= ferry_len; ++i)
    ferry[0][i].length = ferry[i][0].length = 0;
    ferry[0][i].prev_row = ferry[i][0].prev_col = 0;

  // Print info
  if (DBG_LV2){
    printf('\nLength of Ferry: %d \n', ferry_len);
    printf('Number of Cars: %d \n\n', total_cars);

    for (i = 0; i < total_cars; ++i)
      printf('Car[%d]: %d length\n',
             i, cars[i]);
    printf('************************************\n');
  }//end if

  // Fill table
  int result = recursive_ferry(0,0,0, ferry_len);

  if (DBG_LV2){
    printf('Result: %d length value\n',  result);
  }

  if (DBG_LV2)
    print_tables();

  // Track back foot steps
  if (DBG_LV2)  printf('tracking(%d, %d, %d)\n\n', ferry_len, ferry_len, total_cars);
  tracking(ferry_len, ferry_len, total_cars);

  // Print results
  if (DBG_LV2) printf('\n SIDE: \n');

  for (i = 1; i < total_cars; ++i)
    switch(side[i]){
      case UNKNOWN:
        if (DBG_LV2) printf('UNKNOWN side[%d]: %d\n', i, side[i]);
        break;

      case RIGHT:
        if (DBG_LV2) printf('RIGHT side[%d]: %d\n', i, side[i]);
        printf('right\n');
        break;

      case LEFT:
        if (DBG_LV2) printf('LEFT side[%d]: %d\n', i, side[i]);
        printf('left\n');
        break;

    };

  return 0;
}

/*
 *
 */
int tracking(int left, int right, int idx_car){

  if (1) printf('\ntracking(%d,%d,%d)\n', left, right, idx_car);

  if (idx_car < 0)
    return;

  if (DBG_LV2) printf('.1 ');

  if (ferry[left][right].length == 0)
    return;

  if (DBG_LV2) printf('.2 ');

  --idx_car;

  int prev_len = (left + right) - cars[idx_car];
  int prev_left = left - cars[idx_car];
  int prev_right = right - cars[idx_car];

  if (DBG_LV2) printf('prev_len: %d = (%d + %d) - %d (car[%d])\n', prev_len, left, right, cars[idx_car], idx_car);

  if (ferry[prev_left][right].length == prev_len && prev_left >= 0){

    if (DBG_LV2) printf('ferry[prev_LEFT: %d][right: %d] MATCH [from RIGHT]\n', prev_left, right);

    side[idx_car] = RIGHT;

    tracking (prev_left, right, idx_car);

  }else  if (ferry[left][prev_right].length == prev_len && prev_right >= 0){

    if (DBG_LV2) printf('ferry[left: %d][prev_RIGHT: %d] MATCH [from LEFT]\n', left, prev_right);

    side[idx_car] = LEFT;    

    tracking (left, prev_right, idx_car);

  }else{

    if (DBG_LV2) printf('ferry[prev_left][right] and ferry[left][prev_right] DO NOT MATCH\n');
    tracking (left, right, idx_car);  

  }//end if

  return;
}

/*
 *
 */
int recursive_ferry(int left, int right, int idx_car, int ferry_len){

  if (DBG_LV1) printf('r_f(left: %d, right: %d, idx_car: %d (car_len: %d) \n',
                      left, right, idx_car, cars[idx_car]);

  if (left > ferry_len || right > ferry_len || idx_car > total_cars)
    return 0;

  if (ferry[left][right].length > 0){
    if (DBG_LV3) printf('++Return length: %d \n', ferry[left][right].length);
    return ferry[left][right].length;
  }// end if

  // Store value in ferry
  ferry[left][right].length += (left + right);

  // Record foot steps
  int nxt_row = ferry[left][right].prev_row = left;
  int nxt_col = ferry[left][right].prev_col = right;

  //
  int rtn_left = recursive_ferry(left + cars[idx_car], right, idx_car + 1, ferry_len);
  int rtn_right = recursive_ferry(left, right + cars[idx_car], idx_car + 1, ferry_len);

  if (DBG_LV1 && (rtn_left == 0))
    printf('L>');

  if (DBG_LV1)
    printf('[%d,%d](%d | %d)', nxt_row, nxt_col, rtn_left, rtn_right);

  if (DBG_LV1 && (rtn_right == 0))
    printf('<R');

  if (DBG_LV2) printf('\n');
  // Obtain the result of the best route
  return max(rtn_left, rtn_right);
}                    

/*
 *
 */
int print_tables(void){

    printf('\n\nTABLE\n ');
    for (i = 0; i <= ferry_len; ++i)
      printf(' %d ',i);
    printf('\n');

    for (i = 0; i <= ferry_len; ++i){
      for (j = 0; j <= ferry_len; ++j){
        if (j == 0) printf('%d', i);
        printf (' %d ', ferry[i][j].length);
      }// end for
      printf('\n');
    }//end for
    printf('\n');

    printf('\n TABLE XY\n ');
    for (i = 0; i <= ferry_len; ++i)
      printf(' [ %d ]',i);
    printf('\n');

    for (i = 0; i <= ferry_len; ++i){
      for (j = 0; j <= ferry_len; ++j){
        if (j == 0) printf('%d ', i);
        printf('[%d,%d] ', ferry[i][j].prev_row, ferry[i][j].prev_col);
      }//end for
      printf('\n');
   }//end for
   printf('\n');

  return 0;
}

If you encounter any problems or errors, please let me know by providing an example of the code, input, output, and an explanation. Thanks.

Share
Leave a comment

Example of Knapsack Algorithm

Example of Knapsack algorithm.

NOTIFICATION: These examples are provided for educational purposes. Using this code is under your own responsibility and risk. The code is given ‘as is’. I do not take responsibilities of how they are used.

knapsack.c:

/**
 * Knapsack Algorithm
 * @author: Alejandro G. Carlstein R. M.
 * @description: Simple Knapsack algorithm
 */
#include <stdio.h>

/* Macros Functions */
#define max(a,b) \
           ({ typeof (a) _a = (a); \
              typeof (b) _b = (b); \
            _a > _b ? _a : _b; })

/* Debugging flags */
#define DBG_LV1 0
#define DBG_LV2 0

/* Constants */
#define MAX_STRING_LEN 80
#define MAX_ITEMS 100
#define MAX_WEIGHT 1000

/* This is an item we can put into the knapsack. */
typedef struct{
  char name[MAX_STRING_LEN];
  int weight;
  int value;
} item;

/* Our dynamic programming table element.  We have the value
 * that we can store, and also a way to remember what we selected.
 */
typedef struct{
  int value;
  int prev_row;
  int prev_column;
} prog;

void print_table(int num_items, int max_weight);
void print_table_prev_xy(int num_items, int max_weight);

/* The actual DP table, and the items.  Note that we have an extra
 * row and column in the table for the 'zero elements' and 'no weight'
 * situation.
 */
prog table[MAX_ITEMS + 1][MAX_WEIGHT + 1];

item items[MAX_ITEMS];

int main(int argc, char *argv[]){

  int num_items; // Number of items
  int w; // Weight
  int max_weight;
  int n; // Item number;
  int i, j;
  int diff_weight;

  /* Read in the maximum weight and number of items. */
  scanf('%d %d', &max_weight, &num_items);

  if (DBG_LV2){
    printf('\nMax Weight: %d, Number of Items: %d \n\n', max_weight, num_items);
    printf('READ ITEMS\nw v name\n');
  }//end if

  /* Read in the items */
  for (n = 0; n < num_items; ++n){
      scanf('%d %d %s',
            &items[n].weight,
            &items[n].value,
            items[n].name);

     if (DBG_LV1)
        printf('%d %d %s\n',
               items[n].weight,
               items[n].value,
               items[n].name);
  }//end for

  if(DBG_LV2)
    printf('\n');

  /* Initialize the first row of the table. */
  for (w = 0; w <= max_weight; ++w){
      table[0][w].value = 0;
      table[0][w].prev_row = table[0][w].prev_column = -1;
  }//end for

  // Fill in the table
  // Your code goes here.
  // Should be a for loop for the items, a for loop for the weight,
  // and inside all of that, a few if statements to determine if you
  // can take an item -- and if so, do you want to?
  //
  // I strongly recommend printing out EVERY DECISION your program
  // makes while debugging things -- and feed your program very small
  // problems until it's running.
  //
  // Debugging code is an important skill.  If you can work through a
  // problem by hand, you should be able to get your code to solve the
  // same thing.

  /* Initialize the first column of the table */
  for (i= 0; i <= num_items; ++i){
    table[i][0].value = 0;
  }

  if (DBG_LV2){
    printf('TABLE VALUES\n');
    print_table(num_items, max_weight);
  }//end if

  if (DBG_LV2){
    printf('TABLE PREVIOUS COORDINATES\n');
    print_table_prev_xy(num_items, max_weight);
  }//end if

  // Perform knapsack and find maximun value
  for (i = 1; i <= num_items; ++i){

    for (w = 0; w <= max_weight; ++w){

  		table[i][w].prev_row = i - 1;
		  table[i][w].prev_column = w;			

			// Check if item fit inside the knapsack

			if(items[i - 1].weight <= w) {

        int diff_weight = w - items[i - 1].weight;

        // Check which value is higher
				table[i][w].value = max((items[i - 1].value +
                    				    table[i - 1][diff_weight].value),
                    				    table[i - 1][w].value);

        // Keep track of the previous column
				if(table[i][w].value > table[i - 1][w].value)

					table[i][w].prev_column = diff_weight;

			}else{

				table[i][w].value = table[i - 1][w].value;

			}//end if

    }//end for

  }//end for

  if (DBG_LV2){
    printf('************\n\n');
  }//end if

  if (DBG_LV2){
    printf('TABLE VALUES\n');
    print_table(num_items, max_weight);
  }//end if

  if (DBG_LV2){
    printf('TABLE PREVIOUS COORDINATES\n');
    print_table_prev_xy(num_items, max_weight);
  }//end if

  // In my code, the maximum value is here.
  // I can use the prev_row and prev_column to trace back the solution.
  if (DBG_LV1)
    printf('Maximum value is %d\n', table[num_items][max_weight].value);

  if (DBG_LV2){
    printf('************\n\n');
  }//end if

  // Print results:

  w = max_weight;

  int count = -1;

	int t;

	int total_weight = 0;

  item *p_items[MAX_ITEMS];

	for(i = num_items;
	    i > 0;
	    t = w,
	    w = table[i][w].prev_column,
	    i = table[i][t].prev_row){

		if(table[i][w].value != table[i - 1][w].value){

			total_weight += items[i - 1].weight;

			p_items[++count] = &items[i - 1];

	  }//end if

	}//end for

	printf('%d\n', table[num_items][max_weight].value);

	printf('%d\n', total_weight);

  for (i = 0; i <= count; ++i){

    printf('%d %d %s \n',
           p_items[i]->weight,
           p_items[i]->value,
           p_items[i]->name);

  }//end for

}

/*
 *
 */
void print_table(int num_items, int max_weight){

  int w,i;

   for (i = 0; i <= num_items; ++i){
     for (w = 0; w <= max_weight; ++w){
       printf('%d ', table[i][w].value);
    }//end for
    printf('\n');
   }//end for
   printf('\n');

}

/*
 *
 */
void print_table_prev_xy(int num_items, int max_weight){

  int w,i;

   for (i = 0; i <= num_items; ++i){
     for (w = 0; w <= max_weight; ++w){
       printf('[%d,%d] ', table[i][w].prev_row, table[i][w].prev_column);
    }//end for
    printf('\n');
   }//end for
   printf('\n');

}

input.txt:

5
4
2 3 item_A
3 4 item_B
4 5 item_C
5 6 item_D

If you encounter any problems or errors, please let me know by providing an example of the code, input, output, and an explanation. Thanks.

Share
Leave a comment