Dijkstra's Shortest Path Implemented with Min Heap - c++

I am trying to implement Dijksta's shortest path using a min heap, but I am having issues with the distance field not updating correctly after performing relaxation. I also get segmentation fault when trying some test cases and I am not sure why. On pressing R,the program should read in a graph, and build the edge adjacency list of the graph. The edge adjacency list is an array (indexed by the vertices) of singularly linked lists, where the list according to a node v denotes the outgoing neighbors of node v.This is built using the graphinput.txt and the buildGraph function I outline at the bottom; The input text file is the following where 25 and 50 are the number of vertices and edges respectively:
25 50
1 1 3
1 6 2
1 2 7
1 11 1
6 11 3
11 6 2
7 1 4
11 12 4
2 7 10
7 2 10
16 12 7
21 16 4
21 22 1
22 21 2
3 1 5
18 21 1
18 22 3
22 23 5
12 18 8
18 12 7
7 13 3
12 8 2
2 8 1
2 9 3
4 3 4
5 4 7
10 5 3
4 10 10
14 4 15
15 10 8
10 15 6
10 15 7
8 13 2
8 9 1
9 9 4
13 18 1
23 23 7
23 24 4
23 14 1
24 13 9
14 19 1
19 24 1
15 14 2
14 20 16
14 25 30
20 25 15
24 25 26
23 25 8
25 15 2
17 16 13
On reading F S T 1, the program is to print the length of the shortest path from node s to node t.
On reading F S T 0, the program is to output the shortest path from node s to node t.
If the nodes are not reachable it is to output an error.
Here are the structs I am using where d in ELEMENT is the distance, p is the parent and key is the value. In heap, H is an array of type ELEMENT with index ranging from 0 to capacity
These are my heap structs:
struct ELEMENT{ //declaring the element struct with a key
int key;
int d;
int p;
};
struct HEAP{ //declaring the heap struct with a capacity size and a pointer h
int capacity;
int size;
ELEMENT *h;
};
My graph structs:
struct GRAPH{
int v;
int e;
struct ELEMENT *h;
struct LIST** A;
};
struct LIST{
int neighbor;
int weight;
struct LIST* next;
};
I then use the following heap functions:
ELEMENT deleteMin(GRAPH *g){
ELEMENT trueMin;
if(g->v >=1){ //proceeds only if the heap size is greater than or equal to 1
trueMin = g->h[1]; //initializing element variable for the min that gets deleted
}
if(g->v < 1){ //if the heap is empty print this error
cout << "Error: heap empty" << endl;
}
else{
ELEMENT min = g->h[1];
g->h[1] = g->h[g->v];
g->v--;
minHeapify(g,g->h[1].key);
trueMin = min; //else min is equal to first element, is swapped with the last, size is decreased, and minheapfiy is called
}
return trueMin;
}
void decreaseKey(GRAPH *g, int index, int value){
if(index > g->v || index < 1){ //if the index is greater than the size of the index is less than 1 print error
//cout<< "Error: invalid index" << endl;
return;
}
if(value > g->h[index].d){// if the value trying to be increased is greater than the current index value print error
//cout << "Error: new key is bigger than current key" << endl;
return;
}
else{
g->h[index].d = value; //else set the index equal to the key value and swap the parent until the parent has a less value
while( index > 1 && g->h[parent(index)].d > g->h[index].d){
swap(&g->h[index], &g->h[parent(index)]);
index = parent(index);
}
}
}
void minHeapify(GRAPH *g, int i){ //minHeapify algorithm to maintain min heap property where the parent of any given node is always less than its children
int smallest = 0;
int l = left(i);
int r = right(i);
if(l <= g->v && g->h[l].d < g->h[i].d){ //checking if children exist
smallest = l;//setting the smallest equal to left if the left is smaller
} else{
smallest = i;
}
if(r <= g->v && g->h[r].d < g->h[smallest].d){ //checking if children exist
smallest = r;//setting the smallest equal to right if the right is smaller
}
if(smallest != i){ //if the smallest is not equal to i entered by user then swap and minHeapify function
int temp = g->h[i].d;
int temp1 = g->h[i].key;
int temp2 = g->h[i].p;
g->h[i].key = g->h[smallest].key;
g->h[i].d = g->h[smallest].d;
g->h[i].p = g->h[smallest].p;
g->h[smallest].key = temp;
g->h[smallest].d = temp1;
g->h[smallest].p = temp2;
minHeapify(g, smallest);
}
}
void buildHeap(GRAPH *g){
for(int i = floor(g->v/2); i >= 1; i--){
minHeapify(g, i); //performing the buildHeap operation
}
}
int parent(int i){
return floor(i/2);//parent function to return parent node
}
int left(int i){//left function to return left node
return 2 * i;
}
int right(int i){//right function to return right node
return (2 * i + 1);
}
void swap(ELEMENT *a, ELEMENT *b){ //swaps elements using pointers and a temp variable
ELEMENT temp;
temp = *a;
*a = *b;
*b = temp;
return;
}
For my graph, I use the following functions:
GRAPH* initializeGraph(){ //initializing the graph
GRAPH *g = new GRAPH;
g->v=0;
g->h=nullptr;
g->A=nullptr;
g->e=0;
return g;
}
void initializeSingleSource(GRAPH *g, int s)
{
for (int i = 1; i <= g->v; i++)
{
g->h[i].d = INT_MAX - 1000; //setting all the distances to infinity
g->h[i].p = -1; //setting parent field to nonexistent
}
g->h[s].d = 0; //setting the source distance to 0 to start the algorithm
//g->h = new ELEMENT[g->v + 1];
}
void relax(GRAPH *g, int u, int v, int w)
{
int uindex = 0; //variables to search for the index of u and v
int vindex = 0;
for(int i = 1; i <= g->v; i++){ //searching
if(g->h[i].key == u){
uindex = i;
break;
}
}
for(int i = 1; i <= g->v; i++){ //searching
if(g->h[i].key == v){
vindex = i;
break;
}
}
if (g->h[vindex].d > g->h[uindex].d + w) //performing relaxation on indices
{
g->h[vindex].d = g->h[uindex].d + w;
g->h[vindex].p = u;
decreaseKey(g, g->h[vindex].d, w + g->h[uindex].d); //calling decreasekey to maintain minheap property
}
}
void Dijkstra(GRAPH *g, int s, int t, int flag) //s and t are source and target nodes flag determines what to print
{
g->h = new ELEMENT[g->v + 1];
for (int i = 1; i <= g->v; i++) { //setting i
g->h[i].key = i;
}
initializeSingleSource(g,s); //setting initial fields
std::vector<ELEMENT> S; //vector to hold extracted min elements
buildHeap(g); //calling buildheap on g
//cout << g->h[s].d << endl;
while (g->v > 0)
{
ELEMENT u = deleteMin(g); //extracting min
S.push_back(u);
LIST *temp = g->A[u.key]; //pointer for adjacency list
while(temp){
relax(g, u.key,temp->neighbor,temp->weight); //performing relaxation
cout << "update " << temp->neighbor << " distance to " << g->h[temp->neighbor].d << endl; //for debugging purposes
temp = temp->next;
}
}
for(int i = 0; i < S.size(); i++){
if(S[i].key == t){
if(S[i].d == INT_MAX - 1000){ //if distance is still infinity after relaxation then error
std::cout << "Error: node " << t << " not reachable from " << s << std::endl;
}
else{
if(flag == 1){ //if flag is 1 then output the length of the shortest path
std::cout << "LENGTH: " << S[i].d << std::endl;
}
// if (flag == 0 && s == t){
// cout << "PATH: " << s << endl; //wrote this to get more test cases passing without solving real problem
//}
else if(flag == 0){ //if 0 output the path for shortest distance
vector<int> path;
int temp = t;
while(temp != -1){ //while temp os not -1 loop through vector
for(int i = 0; i < S.size(); i++){
if(S[i].key == temp){
path.insert(path.begin(), temp); //insert path until -1
temp = S[i].p;
break;
}
}
}
std::cout << "PATH: ";
for(int i = 0; i < S.size(); i++){
std::cout << path[i]; //printing path as comma separated list
if(i < path.size() - 1){
std::cout << ", ";
}
}
std::cout << std::endl;
}
}
}
}
delete g->h;
}
void buildGraph(GRAPH *g)
{
//GRAPH *g = new GRAPH;
ifstream myfile("Ginput.txt"); //building the adjacency list
int v1 = 0, e1 = 0;
myfile >> v1 >> e1;
if (v1 == 0 || e1 == 0){
std::cout << "Errorr: unable to open file " << std::endl;
}
g->v = v1;
g->e = e1;
g->h = nullptr;
g->A = new LIST *[v1 + 1];
for (int i = 1; i <= v1; i++)
{
g->A[i] = NULL;
}
int u,v,w;
while (myfile >> u >> v >> w)
{
LIST *temp = new LIST;
temp->neighbor = v;
temp->weight = w;
temp->next = NULL;
if (g->A[u] == NULL)
{
g->A[u] = temp;
}
else
{
temp->next = g->A[u];
g->A[u] = temp;
}
}
myfile.close();
}
And this is an example of the output I get when I print what relax is doing in my while loop of dijkstra function.
R
COMMAND: R
F 1 1 1
COMMAND: F 1 1 1
update 11 distance to 32712
update 2 distance to 32718
update 6 distance to 32713
update 1 distance to 2147482647
update 15 distance to 32713
update 25 distance to 2147482647
update 13 distance to 32720
update 25 distance to 2147482647
update 14 distance to 32712
update 24 distance to 2147482647
update 23 distance to 2147482647
update 23 distance to 2147482647
update 21 distance to 2147482647
update 22 distance to 2147482647
update 16 distance to 32715
update 25 distance to 2147482647
update 24 distance to 2147482647
update 12 distance to 32718
update 22 distance to 2147482647
update 21 distance to 2147482647
update 16 distance to 32715
update 12 distance to 32718
update 14 distance to 32712
update 10 distance to 32719
update 25 distance to 2147482647
update 20 distance to 2147482647
update 19 distance to 2147482647
update 4 distance to 32726
update 18 distance to 2147482647
update 8 distance to 32713
update 18 distance to 2147482647
update 12 distance to 32718
update 6 distance to 32713
update 15 distance to 32713
update 15 distance to 32713
update 5 distance to 32714
update 9 distance to 2147482647
update 9 distance to 2147482647
update 13 distance to 32720
update 13 distance to 32720
update 2 distance to 32718
update 1 distance to 32713
update 11 distance to 32712
update 4 distance to 32726
update 10 distance to 32719
update 3 distance to 2147482647
update 1 distance to 32718
update 9 distance to 2147482647
update 8 distance to 32713
update 7 distance to 2147482647
LENGTH: 0
F 6 11 0
COMMAND: F 6 11 0
update 11 distance to 32714
update 15 distance to 32713
update 25 distance to 2147482647
update 13 distance to 32720
update 25 distance to 2147482647
update 14 distance to 32712
update 24 distance to 2147482647
update 23 distance to 2147482647
update 23 distance to 2147482647
update 21 distance to 2147482647
update 22 distance to 2147482647
update 16 distance to 32715
update 25 distance to 2147482647
update 24 distance to 2147482647
update 12 distance to 32718
update 22 distance to 2147482647
update 21 distance to 2147482647
update 16 distance to 32715
update 12 distance to 32718
update 14 distance to 32712
update 10 distance to 32719
update 25 distance to 2147482647
update 20 distance to 2147482647
update 19 distance to 2147482647
update 4 distance to 32726
update 18 distance to 2147482647
update 8 distance to 32713
update 18 distance to 2147482647
update 12 distance to 32718
update 6 distance to 3
update 15 distance to 32713
update 15 distance to 32713
update 5 distance to 32714
update 9 distance to 2147482647
update 9 distance to 2147482647
update 13 distance to 32720
Segmentation fault (core dumped)
This is the piece of main where I use Dijkstra function:
case 'F':
printf("COMMAND: %c %d %d %d\n",c ,f, i, v);
if (!g) {
std::cout << "Error: graph not initialized" << std::endl;
break;
}
if(f > 25 || f < 1 || i > 25 || i < 1){
if (v != 0 && v != 1){
std::cout << "Error: one or more invalid nodes" << std::endl;
std::cout << "Error: invalid flag value" << std::endl;
break;
}
}
if(f > 25 || f < 1 || i > 25 || i < 1){
std::cout << "Error: one or more invalid nodes" << std::endl;
break;
}
if (v != 0 && v != 1) {
std::cout << "Error: invalid flag value" << std::endl;
break;
}
Dijkstra(g,f,i,v);
buildGraph(g); //called to avoid errors when extractmin is called to decrease graph size
break;
If anyone could please tell me what I am doing incorrectly, I would greatly appreciate it.

Related

Kruskal algorithm, cycles and unvisited vertices

Algorithm does not pass through vertex 1(Z) and 4(B). Cycles are for vertices 12-13-14(S-T-K) and 13-15-16(T-L-R), how to fix it?
Below is the command, my code, graph, my output and the input file.
The input file contains the data of one connected graph. Its first line contains an integer Nv that specifies the number of edges of the graph. Then there are Nv lines containing descriptions of the consecutive vertices. The description of each node contains a positive integer corresponding to its identifier and a text string corresponding to its name. It can be assumed that both the number of vertices and the identifiers will not exceed 32,767, the length of the name will not be more than 8 characters, and it will only contain letters or numbers. The next line is the number Ne that specifies the number of edges in the graph. Then there are Ne lines containing the description of the subsequent edges. The description of each edge contains three positive integers, the first two correspond to the identifiers of the vertices connected by the given edge, the third is the weight of this edge.
The output should be exactly as many lines as the edges contain the Minimal Spanning Tree, each line should contain information about one edge. The information for each edge should contain the names of the vertices and the edge weight separated by spaces.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct Vertex
{
int id;
char name[8];
};
struct Edges
{
int source;
int destination;
int weight;
};
void quickSort(Edges* tab, int left, int right)
{
if (right <= left)
{
return;
}
int i = left - 1, j = right + 1, pivot = tab[(left + right) / 2].weight;
while (1)
{
while (pivot > tab[++i].weight);
while (pivot < tab[--j].weight);
if (i <= j)
{
swap(tab[i].source, tab[j].source);
swap(tab[i].destination, tab[j].destination);
swap(tab[i].weight, tab[j].weight);
}
else
{
break;
}
}
if (j > left)
{
quickSort(tab, left, j);
}
if (i < right)
{
quickSort(tab, i, right);
}
}
int main()
{
int vertexnumber;
int edgenumber;
Edges* edgeList{};
vector<Edges> MST;
vector<Vertex> vertexList;
cin >> vertexnumber;
for (int i = 0; i < vertexnumber; i++)
{
vertexList.push_back(Vertex());
cin >> vertexList[i].id;
cin >> vertexList[i].name;
}
cin >> edgenumber;
edgeList = new Edges[edgenumber];
for (int i = 0; i < edgenumber; i++)
{
cin >> edgeList[i].source;
cin >> edgeList[i].destination;
cin >> edgeList[i].weight;
}
quickSort(edgeList, 0, edgenumber);
int iterator = 0;
for (int i = 0; i < edgenumber; i++)
{
bool isLoop = false;
int helper = edgeList[i].source;
for (int j = 0; j < MST.size(); j++)
{
for (int k = 0; k < MST.size(); k++)
{
if (MST[k].source == helper)
{
helper = MST[k].destination;
break;
}
if (MST[k].destination == helper)
{
helper = MST[k].source;
break;
}
}
if (edgeList[i].destination == helper)
{
isLoop = true;
break;
}
}
if (!isLoop)
{
MST.push_back(Edges());
MST[iterator].destination = edgeList[i].destination;
MST[iterator].source = edgeList[i].source;
MST[iterator].weight = edgeList[i].weight;
iterator++;
if (MST.size() >= vertexnumber - 1)
{
break;
}
}
}
for (int i = 0; i < MST.size(); i++)
{
for (int j = 0; j < vertexList.size(); j++)
{
if (vertexList[j].id == MST[i].source)
{
cout << vertexList[j].name << " ";
break;
}
}
for (int j = 0; j < vertexList.size(); j++)
{
if (vertexList[j].id == MST[i].destination)
{
cout << vertexList[j].name << " ";
break;
}
}
cout << MST[i].weight << endl;
}
}
S K 60
D O 82
O S 96
F P 108
T K 109
P C 110
W E 115
S T 124
E T 130
G N 135
T R 136
L R 138
F D 139
T L 142
G C 145
16
1 Z
2 G
3 N
4 B
5 F
6 P
7 C
8 W
9 E
10 D
11 O
12 S
13 T
14 K
15 L
16 R
34
1 2 288
1 5 175
1 6 192
2 3 135
2 6 246
2 7 145
3 4 188
3 7 177
3 8 174
4 8 179
4 15 213
5 6 108
5 10 139
6 7 110
6 9 187
6 10 147
6 11 203
7 8 218
7 9 172
8 9 115
8 13 146
8 15 153
9 11 168
9 12 174
9 13 130
10 11 82
11 12 96
12 13 124
12 14 60
13 14 109
13 15 142
13 16 136
14 16 148
15 16 138
There are at least two issues with your code:
When you call your quicksort implementation you should start it with edgenumber - 1 as right border index, otherwise you access uninitialised data.
Your loop detection is not correct because you don't care for the case where there are already three or more edges in MST with the same vertex. Here the path can split but you just follow one of them. Thus you add also cyclic edges to MST and the limit of MST.size() >= vertexnumber - 1 is reached before you could link all vertices to the tree.
I hope this helps. There are plenty of implementations in the net (e.g. see external links in the wikipedia article) where you can study how others have solved the task of loop detection. But if my assumption is right that you are doing this as homework, of course, it is better to try yourself.

Logical Error in given program cannot find it

In this problem we are given two arrays attackArray and defArray both of size N.
Now we think each array element to be a say, solider.
We need to output the particular element which is greater than its neighbours & greater than their sum. If multiple elements can the output then output the largest one.
-1 If no such element is found.
Custom input I tried to run it with
Input
4
4
1 1 4 1
3 4 2 1
7
5 4 5 4 5 4 5
3 2 4 7 2 5 9
3
5 8 1
5 6 20
20
46 35 17 37 39 48 10 49 44 11 36 4 2 22 16 41 26 8 15 40
4 41 6 35 49 50 28 46 22 17 13 36 31 2 33 14 150 47 29 39
Output
3
-1
20
-1
.Last output should've been 150.
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin >> T;
if (T > 100 || T < 1)
return 0;
do {
vector<int> ans;
int N;
cin >> N;
if (N > 100 || N < 3)
return 0;
vector<long long int> attackArray(N), defArray(N);
for (int i = 0; i < N; i++) {
cin >> attackArray.at(i);
}
for (int i = 0; i < N; i++) {
cin >> defArray.at(i);
}
if (defArray.at(0) > attackArray.at(1) && defArray.at(0) > attackArray.at(N - 1) && defArray.at(0) > attackArray.at(1) + attackArray.at(N - 1)) {
ans.push_back(defArray.at(0));
}
if (defArray.at(N - 1) > attackArray.at(0) && defArray.at(N - 1) > attackArray.at(N - 2) && defArray.at(N - 1) > attackArray.at(0) + attackArray.at(N - 2)) {
ans.push_back(defArray.at(N - 1));
}
for (int i = 1; i < N - 1; i++) {
int nexti, previ;
nexti = i + 1;
previ = i - 1;
if (defArray.at(i) > attackArray.at(nexti) && defArray.at(i) > attackArray.at(previ) && defArray.at(i) > attackArray.at(nexti) + attackArray.at(previ)) {
ans.push_back(defArray.at(i));
}
else {
ans.push_back(-1);
break;
}
}
sort(ans.begin(), ans.end(), greater<int>());
cout << ans[0] << endl;
T--;
} while (T != 0);
return 0;
}
It works for the first line because the first element in defArray is larger than the attack of the neighbours so it doesn't need to enter the loop (you check specially for the first element).
It works for the third line because the last element in defArray is larger than the attack of the neighbours so it doesn't need to enter the loop (you check specially for the last element).
It doesn't work for any item in the loop after the first one because as soon as something in defArray is not larger than the attack of the neighbours you call break; and exit the loop. You need to check every element in defArray but the loop stops as soon as any element fails. Why are you calling break; anyway?
I haven't tested all the boundary conditions but removing the break; does seem to fix it...

Finding an element in a 2d array given its position on a spiral

I am trying to solve a problem which involves a spiral ordering of the elements of a matrix and how to calculate the corresponding row and column.
All the queries are in the form SZ P, where SZ is the size of the matrix and P the position in spiral starting from the center and ending in the top right corner.
The output has to be the cartesian coordinates (row and column) of the P point in the spiral (starting with line 1 at the bottom and column 1 at the left).
What I did to solve it, is doing it in reverse way, starting from the right corner and going on until the center):
while(k <= SZ && l <= SZ && m > 0 && n > 0)
{
right:
for(int i = k; i <= m; ++i) /// right
{
a[i][m] = no;
--no;
}
--m;
down:
for(int i = m; i >= k; --i) /// down
{
a[n][i] = no;
--no;
}
--n;
left:
for(int i = n; i >= k; --i) /// left
{
a[i][k] = no;
--no;
}
++k;
up:
for(int i = k; i <= m; ++i) /// up
{
a[l][i] = no;
no--;
}
++l;
///where l,k,n,m are:
/// k start row index
/// n end row index
/// l start column index
/// m end column index
}
The code works well on a 3x3 matrix, it outputs this matrix:
3 2 9
4 1 8
5 6 7
So, what I'm trying to find out now is how to find the cartesian coordinates of the point P in matrix without storing the matrix in memory, because the size limit is 100000.
Example Input:
3 1
3 3
3 9
5 9
5 10
Example Output:
Line = 2, column = 2.
Line = 3, column = 1.
Line = 3, column = 3.
Line = 4, column = 4.
Line = 5, column = 4.
Augmenting the spiral slightly, a pattern emerges...
31 30 29 28 27 26
32 13 12 11 10 (25)
33 14 03 02 (09) 24
34 15 (04)[01] 08 23
35 (16) 05 06 07 22
(36) 17 18 19 20 21
Squares of odd numbers 1^2, 3^2, 5^2 are located on the NorthEast facing diagonal, and squares of even numbers on SouthWest facing diagonal.
Also between any N^2, (N+1)^2 there are 2N(+1) elements; the first N are located on horizontal line and the rest on vertical line.
Placing the first item (N=1) at x=0, y=0, the coordinate for nth item is:
void spiral_to_cartesian(int &x, int &y, int n)
{
x = 0; y=0;
if (n <= 1) return;
int a = sqrt((double)n);
int remainder = n - a*a;
if (a & 1)
{
x+=(a/2); y-=(a/2);
if (remainder > 0 && remainder <= n)
{
--y; x-=remainder-1;
}
else if (remainder > n)
{
x-=n; y+=remainder - n - 1;
}
}
else
{
x-=(a/2); y+=(a/2)-1;
if (remainder > 0 && remainder <= n)
{
++y; x+=remainder-1;
}
else if (remainder > n)
{
x+=n; y-=remainder - n - 1;
}
}
}

Dijkstra's Algorithm - Infinite Loop

As a homework assignment, I am to implement an adjacency list using an array of pointers to linked lists for each vertex. Each linked list has an element <destination> that states the vertex neighbor of adjacency list vertex.
The adjacency list is undirected and unweighted, so I am treating all weights as 1.
/* Adjacency List Node data structure (edge)
* Linked List data structure for storing linked vertices
*/
struct adjacencyListNode
{
int destination;
struct adjacencyListNode *next;
};
/* Adjacency List Vertex data structure (vertex)
* <AdjacencyList> consists of pointers to <n> adjacencyListVertex
*/
struct adjacencyListVertex
{
struct adjacencyListNode *head;
};
I am trying to perform Dijkstra's Algorithm on the adjacency list to find the minimum path from s to t.
Right now I am implementing the following algorithm:
/* Prints the length and path taken of the shortest path in adjacency list between s and t.
* Uses Dijkstra’s algorithm to compute shortest path.
* S: source vertex
* V: destination vertex
*/
void shortestPath(int s, int t) {
int known[size]; // shortest distance to vertex is know
int cost[size]; // distance from source <s> to each vertex
int path[size]; //path
// Initialization: Set all distances to infinity (represented by -1), since arrays have not been visited and graph is positively weighted
for (int index = 0; index<size; index++) {
cost[index] = INFINITY;
known[index] = 0;
}
// Set distance from source->source to 0
cost[s-1] = 0;
// Starting at s, traverse towards all reachable unvisited verticies, visit it and repeat
while (isFinished(known, size) == false) {
// Select a vertex from list of unvisited nodes which has the smallest cost
int cheapestVertex, cheapestValue = INFINITY+1;
for (int costCheck = 0; costCheck<size; costCheck++) {
if ((known[costCheck] == 0) && (cost[costCheck] < cheapestValue)) {
// We found a cheaper unvisited vertex
// cout << "Cheapest vertex: " << costCheck << endl;
cheapestVertex = costCheck;
cheapestValue = cost[cheapestVertex];
}
// cout << "found? " << cheapestVertex << " " << cheapestValue << endl;
}
// cout << "Cheapest vertex: " << cheapestVertex << endl;
// For each unvisited neighbor of our cheapest (unvisited) vertex
adjacencyListNode* iterator = A[cheapestVertex].head; // iterator is our first neighbor
while (iterator)
{
// Calculate the new cost from the current vertex <cheapestVertex>
if (cost[cheapestVertex]+1 < cost[iterator->destination] && known[iterator->destination] == 0) {
cost[iterator->destination] = cost[cheapestVertex]+1;
}
iterator = iterator->next; // move to next neighbor, repeat
}
// cout << "Cheapest vertex: " << cheapestVertex << " known." << endl;
// Mark the current vertex <cheapestVertex> as visited
known[cheapestVertex] = 1;
// DEBUG: (REMOVE BEFORE SUBMISSION)
for (int i = 0; i<size; i++) {
cout << "Vertex " << i << " : known? " << known[i] << ", cost? " << cost[i] << endl;
}
cout << endl;
if (cost[t-1] != INFINITY) break; // We already know shortest path, end.
}
// We know the shortest path cost to t
cout << "Cost to t: " << cost[t] << endl;
}
bool isFinished(int array[], int arraySize) {
bool finished = true;
for (int iterator=0; iterator < arraySize; iterator++) {
if (array[iterator] == 0) {
// vertex not known, we're not done.
finished = false;
}
}
return finished;
}
I am passing the following input, which just adds the stated related vertices and calls my shortest-path algorithm.
0 1
1 2
1 3
2 4
3 5
5 38
6 7
6 10
8 9
11 12
12 13
12 15
12 21
13 14
14 15
16 17
17 18
18 19
19 20
20 39
21 22
22 23
22 31
23 24
23 32
24 25
24 33
25 26
26 27
27 28
28 29
29 30
31 40
34 35
34 37
35 36
36 37
1
shortest-path
My code traverses from 0->1->2->3->4->5->38 and then repeats 38 infinitely.
Does anyone see where my issue is?
You have a few issues. As this is homework, I won't give you the full answers.
Issue 1: What happens if there are nodes that are unreachable from s? This is what is happening in your example.
Hint: You need to work out when to stop the loop (other than the one you have already). Look at your cheapest selection - how would you determine that there isn't a valid one?
Hint #2 - You current loop won't set a value for cheapestVertex if all remaining vertices have a cost of INFINITE, so you will be using an uninitialized value. Maybe check what the cheapest cost you found was before proceeding.
Issue 2: cost[iterator->destination] = cost[cheapestVertex]+1;
Hint: are you sure this is correct to do on every occasion? What if the node already has a cheaper cost, or has already been visited?
Issue 3: You can stop looking once you have t known. No need to check the whole graph. Note: This is an change that you don't necessarily need as your code will work without it.

Modifing Arrays without using <algorithm> functions in C++? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
So first, we start with an array of 50. The range of the values within the array can be 1-100, not repeating. Then we display the highest value of that random array. Then we display the lowest value in the array. Then comes the sorting, which would be easy using the standard library functions in the <algorithm> header, but since it's not allowed, we need to find another way around it. Then sort from high to low.
So, to display this easily... First we start with an array[50] with random numbers between 1-100
72 29 11 41 31 27 21 46 43 40 17 45 30 32 25 15 19 88 22 24 51 34 99 23 26 37 1 4 2 9 33 44 12 39 38 3 47 48 5 42 49 18 54 55 87 16 28 20 50 9
Now we display the highest number
99
Then the lowest
1
The we sort them
1 2 3 4 5 9 9 11 12 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 54 55 72 87 88 99
Then reverse sort them
99 88 87 72 55 54 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 12 11 9 9 5 4 3 2 1
So.. how would I go about doing this without algorithms?
The usual way to do this is by using loops.
For example, to traverse an array, printing every element, we could use a loop like:
for (int i=0; i<50; i++) {
std::cout << array[i] << std::endl;
}
All of the problems you mention, except sorting, can be done using a simple loop like the one above. You'll have to do your own bookkeeping in order to solve the problems, but it shouldn't be too difficult.
As for sorting, that's a more challenging problem. You might start with the wikipedia article to see how that is handled. You probably want to try implementing selection sort.
You can use bitset sort since the range of values of the array is limited to 1-100, and there is no repetition you can have a bitset array of 100 ints where each index specifies can be a 0 (that number isn't in the array) or a 1 (the number is in the array). For example the array [1, 5, 3] can be represented by the bitset array [1, 0, 1, 0, 1].
pseudo code:
MAX_SIZE = 100
bitset = new int[MAX_SIZE]
smallest = biggest = -1
for each value in array {
smallest = value if value < smallest
biggest = value if value > biggest
bitset[value-1] = 1
}
sorted = (i for i in 0..bitset.length - 1 if bitset[i] == 1)
reverse_sorted = (sorted[i] for i in sorted.length-1..0)
Not very professional but works
int array[50], used[50], sortedArray[50], buildSort = 1, genNum, max = 0, min = 101;
bool x;
srand(time(0));
//Array Generator
for(int i = 0; i < 50; i++){
do{
genNum = (1+rand()%100);
x = false;
for(int j =0; j < 50; j++){
if(genNum == used[j]){
x = true;
}
}
}while(x == true);
used[i] = genNum;
array[i] = genNum;
}
cout << "Numbers: ";
for(int d = 0; d < 50; d++){
cout << array[d] << " ";
}
cout << endl << endl;
//Max and Min finder
for(int m = 0; m < 50; m++){
if(array[m] > max){
max = array[m];
}
if(array[m] < min){
min = array[m];
}
}
cout << "Max is: " << max << endl;
cout << "Min is: " << min << endl << endl;
//Sorting
sortedArray[0] = min;
for(int v = min+1; v <= max; v++){
for(int r = 0; r < 50; r++){
if(array[r] == v){
sortedArray[buildSort] = array[r];
buildSort++;
}
}
}
cout << "Sorted: ";
for(int k = 0; k < 50; k++){
cout << sortedArray[k] << " ";
}
cout << endl << endl;
cout << "Reverse sorting: ";
for(int l = 49; l >=0; l--){
cout << sortedArray[l] << " ";
}
Well, I have not checked this code and I'm sure it has some errors in it, but hopefully this will at least give you some ideas and a good base to go off of:
/******************
*
* Your array should have 51 spots.
* The last element should be 0.
*
******************/
uint8_t findMax(uint8_t *arrayToSearch){
// Your array should end in a sentinel value of 0
uint8_t highest = 0;
for(; *arrayToSearch; arrayToSearch++){
highest = (*arrayToSearch > highest) ? *arrayToSearch : highest;
}
return highest;
}
uint8_t findMin(uint8_t *arrayToSearch){
// Your array should end in a sentinel value of 0
uint8_t lowest = 101;
for(; *arrayToSearch; arrayToSearch++){
lowest = (*arrayToSearch < lowest) ? *arrayToSearch : lowest;
}
return lowest;
}
void sortAscending(uint8_t *arrayToSearch){
// sort from low to high
// get count of array (According to your question, it should be 50, but we'll verify)
unsigned short count = 0;
uint8_t *countingPoint;
countingPoint = arrayToSeach; // make countingPoint point to the first element
while(*countingPoint){
count++;
countingPoint++;
}
// now we'll create a second array
uint8_t sortedArray[count];
// now let's begin sorting.
unsigned long int totalIterations = 0;
while(totalIterations < count){
uint8_t currentSmallest = 101; // value which will not ever exist.
signed long int smallestIndex = -1;
unsigned short offset = 0;
uint8_t *startOfArray;
startOfArray = arrayToSearch;
for(; *startOfArray; *startOfArray++, offset++){
if(currentSmallest > *startOfArray){
smallestIndex = offset;
currentSmallest = *startOfArray;
}
} /* end for */
sortedArray[totalIterations] = currentSmallest;
*(smallestIndex + arrayToSearch) = 101; /* set the value above 100 so it will be
skipped in the next for loop */
totalIterations++;
} /* end while */
/* now we'll the sorted values to the array to search */
int i;
for(i=0; i < count; i++){
*(i+arrayToSearch) = sortedArray[i];
}
// and we're done.
}
/*
* We can actually write sortDescending the same way and just modify
* the last loop to put them in reverse order
*/
void sortDescending(uint8_t *arrayToSearch){
// sort from low to high and then order as high to low
// get count of array (According to your question, it should be 50, but we'll verify)
unsigned short count = 0;
uint8_t *countingPoint;
countingPoint = arrayToSeach; // make countingPoint point to the first element
while(*countingPoint){
count++;
countingPoint++;
}
// now we'll create a second array
uint8_t sortedArray[count];
// now let's begin sorting.
unsigned long int totalIterations = 0;
while(totalIterations < count){
uint8_t currentSmallest = 101; // value which will not ever exist.
signed long int smallestIndex = -1;
unsigned short offset = 0;
uint8_t *startOfArray;
startOfArray = arrayToSearch;
for(; *startOfArray; *startOfArray++, offset++){
if(currentSmallest > *startOfArray){
smallestIndex = offset;
currentSmallest = *startOfArray;
}
} /* end for */
sortedArray[totalIterations] = currentSmallest;
*(smallestIndex + arrayToSearch) = 101; /* set the value above 100 so it will be
skipped in the next for loop */
totalIterations++;
} /* end while */
/* now we'll copy the values to the arrayToSearch in reverse order */
int i;
for(i=(count-1); i >= 0; i--){
*(i+arrayToSearch) = sortedArray[i];
}
// and we're done.
}
/* calling these */
int main(){
uint8_t yourArray[51];
// ... your code to populate this array
yourArray[50] = 0; // set the last spot to 0.
uint8_t highest = findMax(yourArray);
uint8_t lowest = findMin(yourArray);
// now make yourArray sorted by lowest to highest
sortAscending(yourArray);
// ... Whatever you need to do with it in ascending order.
// now make it sorted by highest to lowest
sortDescending(yourArray);
// ... Whatever you need to do with it in descending order.
return 0;
}
I'm a C-programmer so this is a rather C-style answer.
Some additional information that might be helpful can be found at:
http://www.sanfoundry.com/c-program-sort-array-ascending-order/
http://www.programmingsimplified.com/c/source-code/c-program-bubble-sort
http://en.wikipedia.org/wiki/Sorting_algorithm
The Wikipedia page (last link) might seem a little overwhelming, but there is a lot of great content on it.
I hope this will be of some help to you. Again, I'm not sure if the code I included will work properly. It's merely meant to convey the general idea.