Implementing a scheduling algorithm (assignment) [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So I am on my 2nd year of computer science and I am struggling with a part of one of my assignments.
Basically, we had to make a stack, a queue and a scheduling algorithm.
I've made the stack and queue part which will technically give me a pass, but I would like to do the remaining part as well just to be sure.
We're allowed to use ONLY iostream library, nothing else.
These are the .h files provided by our teacher:
http://pastebin.com/TcBzULZj
We HAVE to use these.
I am struggling with the algorithm as it is supposed to be a subclass of queue, using an integer for priority and storing integer values to represent process IDs.
How should I approach that?
I am not asking you to do my homework for me or anything like that, I just want to tips and a little push in the right direction :)
############################################
EDIT
I tried to do it this way:
http://pastebin.com/mFchEc6T
It does compile and start, but as soon as I try to do anything in the program it gives some memory error and turns off my program.
I guess there's something wrong with the pointers but I dont know what.
Basically the idea behind that function was to go through all the nodes from the top of the queue and compare their priority to the priority of "temp" node.
It would swap places with nodes as long as "temp" had higher priority than them (green on picture) and as soon as it hit a node with the same priority (blue) it would stop there and wait for its turn, before nodes with higher priority (red) are done.
I bet these pointers are messed up but I just can't get my head around it for life, even though I struggled with this for like 2 days already.

You can adding a new value with priority P after all values with priorities higher than P.
Pop values from the beginning of the list.
For example:
If you have values 1, 2, 3, 4, 5 with priorities 99, 54, 111, 27, 978
In list you have: 5(978), 3(111), 1(99), 2(54), 4(27).
If you need add value 6 with priority 105, you add it after value 3 with priority 111.

Look at the simple example of queue with priorities.
#include <iostream>
class Queue {
public:
Queue() :
queue( 0 )
{
}
void Push( int value, int priority = 0 );
bool Pop( int& value );
private:
struct Node {
Node* Next;
int Value;
int Priority;
Node( int value, int priority ) :
Next( 0 ),
Value( value ),
Priority( priority )
{
}
};
Node* queue;
Queue( const Queue& );
Queue& operator=( const Queue& );
};
void Queue::Push( int value, int priority)
{
Node* node = new Node( value, priority );
if( queue == 0 || queue->Priority < node->Priority ) {
node->Next = queue;
queue = node;
} else {
Node* i = queue;
while( i->Next != 0 && node->Priority <= i->Next->Priority ) {
i = i->Next;
}
node->Next = i->Next;
i->Next = node;
}
}
bool Queue::Pop( int& value )
{
if( queue == 0 ) {
return false;
}
value = queue->Value;
Node* tmp = queue;
queue = queue->Next;
delete tmp;
return true;
}
int main( int argc, const char* argv[] )
{
Queue queue;
queue.Push( 3, 100 );
queue.Push( 2, 200 );
queue.Push( 1, 500 );
int x;
while( queue.Pop( x ) ) {
std::cout << x << std::endl;
}
return 0;
}

Related

How to move elements in doubly linked list? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have custom list (doubly linked list and not std::list) implemented in my code. My requirement is to move the element by one left or right by updating the references. Is it possible?
class Elem
{
Elem *next;
Elem *prev;
}
.......
void move_element_left(Elem *e)
{
if(e->prev()==NULL)
return; //Left most ... so return
Elem *left = e->prev();
left->next() = e->next();
e->prev() = left->prev();
if (left->next())
left->next()->prev() = left;
if (e->prev())
e->prev()->next() = e;
e->next() = left;
left->prev() = e;
}
.......
int main()
{
ElemList ls;
...
...
move_element_left(e); //e of type Elem *
...
}
Above code works except for the 2nd object in the list which I want to move to left most (or to top most). (i.e. say if list(obj5, obj9, obj11, obj12,..), moving obj9 to the first in the list gives error)
See Bubble-sorting doubly linked list
I assume your Elem class does also contain data, so move the data or - if it's a simple data pointer - swap the pointers: C++ Swapping Pointers.
If that's not possible I would - from a "Don't Repeat Yourself" point of view - reuse those simple linked list functions you most probably already have:
void move_element_left(Elem *e)
{
Elem *left = e->prev();
if(left)
{
remove_element(e);
insert_element_before(e, left);
}
}
Works as designed ?
Following your code in a schema, shows that it works as designed:
void move_element_left(Elem *e)
{
if(e->prev()==NULL)
return; //ok ! Left most ... so return
Elem *left = e->prev(); // ok ! (1)
left->next() = e->next(); // ok ! (2)
e->prev() = left->prev(); // ok ! (3)
if (left->next()) // ok !
left->next()->prev() = left; // ok ! (4)
if (e->prev()) // ok ! e prev is left prev is null
e->prev()->next() = e;
e->next() = left; // ok ! (5)
left->prev() = e; // ok ! (6)
}
Here the schema (sorry for the childish aspect ;-) ):
So the list is in fact fine. The problem is that ElemList certainly contains a pointer to the head of the list . And this pointer still points to the old first and now second element. So the list is then no longer consitent.
How to fix it ?
One way out, would be to make move_element_left() a member function of ElemList. In this case you could take care of the special case where e->left becomes null, in which case you need to update ElemList's pointer to the first element.
Below is the updated code. You need to change the head pointer if the left pointer points to head of double linked list.
//**head is the address of pointer of head of double linked list
void move_element_left(Elem *e,Elem **head)
{
if(e->prev()==NULL)
return; //Left most ... so return
Elem *left = e->prev();
if(left==*head){
*head=e;
}
left->next() = e->next();
e->prev() = left->prev();
if (left->next())
left->next()->prev() = left;
if (e->prev())
e->prev()->next() = e;
e->next() = left;
left->prev() = e;
}

How can i make this algorithm more memory efficient?

I have been working on this piece of code for a couple of days and it seems
to work just fine for search trees of relative small size, but working with higher ones gives segmentation fault.
I have tried to find the specific place where such error comes from by using printing flags, and it seems to break at the is_goal() function. But the code of that function can be assumed as correct.
So the problems seems to be a memory problem, that's why I have the queue in the heap, and also the Nodes that I am creating. But it still crashes.
Are there any more memory saving tricks that can be taking into account that I am not using? Or maybe there is a better way to save such nodes?
It is important to note that I need to use BFS (I can't use A* to make the search tree smaller).
Also if you need to know, the map is a hash table where I save the coloring of the nodes so I don't have duplicates when exploring (This is because the hash saves depending on the state information and not the Node information).
EDIT: i have been told to indicate the goal to accomplish, such is to find the goal state in the search tree, the goal is to be be able to iterate over
big problems like rubik 3x3x3, n-puzzle 4x4 5x5, tower of hanoi and such.To do so, the memory used has to be minimal since the search tree of such problems are really big, the final objective is to compare this algorithm with others like a*, dfid, ida*, and so on. I hope this is enough information.
Node* BFS(state_t start ){
state_t state, child;
int d, ruleid;
state_map_t *map = new_state_map();
ruleid_iterator_t iter;
std::queue<Node*> *open = new std::queue<Node*>();
state_map_add( map, &start, 1);
Node* n = new Node(start);
open->push(n);
while( !open->empty() ) {
n = open->front();
state = n->get_state();
open->pop();
if (is_goal(&state) == 1) return n;
init_fwd_iter( &iter, &state );
while( ( ruleid = next_ruleid( &iter ) ) >= 0 ) {
apply_fwd_rule( ruleid, &state, &child );
const int *old_child_c = state_map_get( map, &child );
if ( old_child_c == NULL ) {
state_map_add( map, &child, 1 );
Node* nchild = new Node(child);
open->push(nchild);
}
}
}
return NULL;
}
I see a number of memory leaks.
open is never deleted but maybe could allocated in the stack instead of in the heap.
std::queue<Node*> open;
More important none of the node you push in the queue are deleted this is probably the origin of very big memory consumption.
Delete the nodes that you remove from the queue and that you don't plan to reuse. Delete the nodes of the queue before your get rid of the queue.
Node* BFS(state_t start ){
state_t state, child;
int d, ruleid;
state_map_t *map = new_state_map();
ruleid_iterator_t iter;
std::queue<Node*> open;
state_map_add( map, &start, 1);
Node* n = new Node(start);
open.push(n);
while( !open.empty() ) {
n = open.front();
state = n->get_state();
open.pop();
if (is_goal(&state) == 1) {
for (std::queue<Node*>::iterator it = open.begin(); it != open.end(); ++it)
delete *it;
return n;
}
else {
delete n;
}
init_fwd_iter( &iter, &state );
while( ( ruleid = next_ruleid( &iter ) ) >= 0 ) {
apply_fwd_rule( ruleid, &state, &child );
const int *old_child_c = state_map_get( map, &child );
if ( old_child_c == NULL ) {
state_map_add( map, &child, 1 );
Node* nchild = new Node(child);
open.push(nchild);
}
}
}
return NULL;
}

Segment tree implementation

I was learning segment tree from this page : http://letuskode.blogspot.com/2013/01/segtrees.html
I am finding trouble to understand various fragments of code.I will ask them one by one.Any help will be appreciated.
Node declaration:
struct node{
int val;
void split(node& l, node& r){}
void merge(node& a, node& b)
{
val = min( a.val, b.val );
}
}tree[1<<(n+1)];
1.What will the split function do here ?
2.This code is used for RMQ . So I think that val will be the minimum of two segments and store it in some other segment.Where the value will be saved?
Range Query Function:
node range_query(int root, int left_most_leaf, int right_most_leaf, int u, int v)
{
//query the interval [u,v), ie, {x:u<=x<v}
//the interval [left_most_leaf,right_most_leaf) is
//the set of all leaves descending from "root"
if(u<=left_most_leaf && right_most_leaf<=v)
return tree[root];
int mid = (left_most_leaf+right_most_leaf)/2,
left_child = root*2,
right_child = left_child+1;
tree[root].split(tree[left_child], tree[right_child]);
//node l=identity, r=identity;
//identity is an element such that merge(x,identity) = merge(identity,x) = x for all x
if(u < mid) l = range_query(left_child, left_most_leaf, mid, u, v);
if(v > mid) r = range_query(right_child, mid, right_most_leaf, u, v);
tree[root].merge(tree[left_child],tree[right_child]);
node n;
n.merge(l,r);
return n;
}
1.What is the use of the array tree and what values will be kept there ?
2.What will this statement : tree[root].split(tree[left_child], tree[right_child]); do ?
3.What will those statements do ? :
node n;
n.merge(l,r);
return n;
Update and Merge Up functions:
I am not understanding those two functions properly:
void mergeup(int postn)
{
postn >>=1;
while(postn>0)
{
tree[postn].merge(tree[postn*2],tree[postn*2+1]);
postn >>=1;
}
}
void update(int pos, node new_val)
{
pos+=(1<<n);
tree[pos]=new_val;
mergeup(pos);
}
Also what should I write inside the main function to make this thing work?
Suppose I have an array A={2,3,2,4,20394,21,-132,2832} , How I can use this code to find RMQ(1,4)?
1.What will the split function do here ?
Nothing: the function body is empty. There may be some other implementation where an action is required. (See Example 3) And see answer to 2b
2.... Where the value will be saved?
In the "val" field of the class/struct for which "merge" is called.
1b.What is the use of the array tree and what values will be kept there ?
Array "node tree[...]" stores all the nodes of the tree. Its element type is "struct node".
2b.What will this statement : tree[root].split(tree[left_child], tree[right_child]); do ?
It calls split for the struct node that's stored at index root, passing the nodes of the split node's children to it. What it actually does to tree[root] depends on the implementation of "split".
3b.What will those statements do ? :
node n; // declare a new node
n.merge(l,r); // call merge - store the minimum of l.val, r.val into n.val
return n; // terminate the function and return n
I'll have to figure out the answers to your last Qs in the context of that code. Will take a little time.
Later
This should build a tree and do a range query. I'm not sure that the code on that page is correct. Anyway, the interface for range_query is not what you'd expect for easy usage.
int main(){
int a[] = { -132, 1, 2, 3, 4, 21, 2832, 20394};
for( int i = 0; i < 8; i++ ){
node x;
x.val = a[i];
update( i, x);
}
node y = range_query(0, 8, 15, 8 + 1, 8 + 4 );
}

How to transform C program into classes

so I've been working on this program and its objective was to use recursion and an adjacency matrix to find how many possible routes a person could take to get through a subway system without going over a track more than once. That was self explanatory for me but now I'm lost on program 2 which is to do the same problem from program 1 in C++ and using three classes and recursion. The classes are suppose to be SubwaySystem, Station, and Track. I don't really know how to go about the transition from a simple adjacency matrix into three classes? It seems counterproductive since it seems more complicated. I have been working on it for a while know and I can't seem to utilize all three classes.
What I have tried: My approach was I created 1 Subway System with 12 Stations, and each station with an array of Tracks. For example, Station A has one station it can go to which is B. In Station A there is an array of 12 tracks but only 1 track is activated. However I keep running to errors since I tried to initialize the arrays in the Track class and then use them in the SubwaySystem class. Then trying to use recursion to get all possible routes makes it that much more difficult. I really don't know how to figure this out.
The adjacency matrix in the my code pretty much maps out the entire connection from station to station. The station are A - L corresponding to each row/column. I don't know how to represent this in c++ without using an adjacency matrix.
My code in C (program 1):
#include <stdio.h>
void routesFinder(int row, int col);
char station[13] = "ABCDEFGHIJKL";
char order[25] = "A";
int subway[12][12] = {{0,1,0,0,0,0,0,0,0,0,0,0},
{1,0,1,1,1,1,0,0,0,0,0,0},
{0,1,0,0,1,0,0,0,0,0,0,0},
{0,1,0,0,1,0,0,0,0,0,0,0},
{0,1,1,1,0,0,1,1,0,0,0,0},
{0,1,0,0,0,0,0,1,0,0,0,0},
{0,0,0,0,1,0,0,0,0,0,1,0},
{0,0,0,0,1,1,0,0,1,1,1,0},
{0,0,0,0,0,0,0,1,0,0,1,0},
{0,0,0,0,0,0,0,1,0,0,1,0},
{0,0,0,0,0,0,1,1,1,1,0,1},
{0,0,0,0,0,0,0,0,0,0,1,0}};
int paths = 0, i = 1;
int main(){
routesFinder(0, 0); //start with first station row, first column
printf("\n%d days before repeating a route.\n", paths);
return 0;
}
void routesFinder(int row, int col) {
while (col < 12) { //go through columns of a row
if (subway[row][col] == 0) { // if no station is found in row
if (row == 11) { // station found
paths++;
printf("Route %d: %s.\n", paths, order);
return;
}
col++;
if (row != 11 && col == 12) { //backtracking from deadend
return;
}
}
if (subway[row][col] == 1) {
order[i] = station[col]; //add station to route
i++; //increment, prepare for next route
subway[row][col] = 0; //no track forward
subway[col][row] = 0; // or backward
routesFinder(col, 0); //recursion, look for path in new row
order[i] = '\0'; //remove route
i--; //decrement, prepare for next route
subway[row][col] = 1; //restore path
subway[col][row] = 1; // restore path
col++; //returning from deadend, check for next open path
if (row != 11 && col == 12) { //return from deadend
return;
}
}
}
}
In general I can tell you that in c++ in particular and in object oriented in general,
each object should have its unique role in the system. Each is encapsulating a behavior and a knowledge that are its own and sole responsibility.
As for you specific problem - Without getting too deeply into the problem, I think the idea would be:
#include <iostream>
#include <string>
#include <vector>
class Track;
typedef std::vector<Track*> TrackList;
class Station
{
public:
Station( std::string name ) : _name( name ){};
~Station(){}
public:
const std::string& GetName() const
{ return _name; }
TrackList& GetTrackList()
{ return _trackList; }
void AddTrack( Track& track )
{ _trackList.push_back( &track ); }
private:
std::string _name;
TrackList _trackList;
};
class Track
{
public:
Track( Station& edgeA, Station& edgeB )
:
_edgeA( edgeA ),
_edgeB( edgeB ),
_wasVisited( false )
{
edgeA.AddTrack( *this );
edgeB.AddTrack( *this );
}
~Track(){}
public:
bool WasVisited() const
{ return _wasVisited; }
void SetVisited()
{ _wasVisited = true; }
public:
Station& GetEdgeA()
{ return _edgeA; }
Station& GetEdgeB()
{ return _edgeB; }
private:
Station& _edgeA;
Station& _edgeB;
bool _wasVisited;
};
class SubwaySystem
{
public:
SubwaySystem() {}
~SubwaySystem() {}
public:
void Traverse( Station& start )
{
TrackList& tracks = start.GetTrackList();
TrackList::iterator it = tracks.begin();
while ( it != tracks.end() )
{
if ( ! (*it)->WasVisited() )
{
std::cout << (*it)->GetEdgeA().GetName() << "-->" << (*it)->GetEdgeB().GetName() << ",";
(*it)->SetVisited();
Traverse( (*it)->GetEdgeB() );
}
++ it;
}
std::cout << std::endl;
}
};
int main()
{
Station A( "A" );
Station B( "B" );
Station C( "C" );
Station D( "D" );
Station E( "E" );
Track AB( A, B );
Track BC( B, C );
Track CA( C, A );
Track CD( C, D );
Track CE( C, E );
Track AE( A, E );
SubwaySystem subway;
subway.Traverse( A );
}
The output to this is
A-->B,B-->C,C-->A,A-->E,C-->E,
C-->D,
Surly you can 'play' with the Traverse function and put the printings in other places,
select another end-recursion condition, etc.
Notice how clean main() is.
You just declare the Stations and the Tracks and the voodoo happens.
Adding more tracks is simple, just describe the link and that's all, the track wad 'added' to the subway.
Other parts of the applications are also very clean, as each class knows exactly what it should and nothing more.
One possible way would to have the subway system hold control over all the stations. The stations would then have tracks that knew the origin (which station they came from) and the destination (which station they could go to).
The adjacency matrix would be broken up, the whole thing is represented inside the subway system, each row/column is represented in the stations, and each 1/0 is represented by the tracks. There would be no track for a zero.
Which paths to take would be decided at the station level, with which tracks being used/destinations already have been gone to. The tracks could have a property that keep track if they have been ridden on.
If you were doing this in C, you might have structures like this
typedef struct node node;
typedef struct edge edge;
typedef struct graph graph;
struct graph { // subway system
node *nodes; // stations
};
struct node { // station
char *name;
edge *edges; // tracks connected to this station
node *next; // next node in graph
bool visited;
}
struct edge { // track
node *src; // from station
node *dst; // to station
edge *next; // next track, this station
bool visited;
}
Transforming that into classes should be easy. Except that they might want you to use stl data structures instead of simply inlining the lists like I did.
The simple recursive graph algorithms map nicely to these data structures.
The idea of recursion for counting is a little hard to get, but let me try to explain at least that part.
So you know how strlen works, in C, right? You walk the array and keep a count. But here's a recursive version
unsigned int strlen(const char * string) {
if (*string == '\0') { return 0; }
else return 1 + strlen(string + 1);
}
Do you see how that works? Not that useful when walking an array where you can use a simple counter, but when you are dealing with issues where there are multiple possible combinations of doing things, or multiple ways of going, it works nicely. For example, if you wanted to count the number of nodes in a binary tree, you might do something like.
unsigned int treecount(NODE * node) {
if (node == NULL) { return 0;}
else return 1 + treecount(node->left) + treecount(node->right);
}
Hopefully that helps. Charlie Burns is probably right that doing it with a graph is a good idea.

c++ directed graph depth first search

I am attempting to write a method DFS method for a directed graph. Right now I am running into a segmentation fault, and I am really unsure as to where it is. From what I understand of directed graphs I believe that my logic is right... but a fresh set of eyes would be a very nice help.
Here is my function:
void wdigraph::depth_first (int v) const {
static int fVertex = -1;
static bool* visited = NULL;
if( fVertex == -1 ) {
fVertex = v;
visited = new bool[size];
for( int x = 0; x < size; x++ ) {
visited[x] = false;
}
}
cout << label[v];
visited[v] = true;
for (int v = 0; v < adj_matrix.size(); v++) {
for( int x = 0; x < adj_matrix.size(); x++) {
if( adj_matrix[v][x] != 0 && visited[x] != false ) {
cout << " -> ";
depth_first(x);
}
if ( v == fVertex ) {
fVertex = -1;
delete [] visited;
visited = NULL;
}
}
}
}
class definition:
class wdigraph {
public:
wdigraph(int =NO_NODES); // default constructor
~wdigraph() {}; // destructor
int get_size() { return size; } // returns size of digraph
void depth_first(int) const;// traverses graph using depth-first search
void print_graph() const; // prints adjacency matrix of digraph
private:
int size; // size of digraph
vector<char> label; // node labels
vector< vector<int> > adj_matrix; // adjacency matrix
};
thanks!
You are deleting visited before the end of the program.
Coming back to the starting vertex doesn't mean you finished.
For example, for the graph of V = {1,2,3}, E={(1,2),(2,1),(1,3)}.
Also, notice you are using v as the input parameter and also as the for-loop variable.
There are a few things you might want to consider. The first is that function level static variables are not usually a good idea, you can probably redesign and make those either regular variables (at the cost of extra allocations) or instance members and keep them alive.
The function assumes that the adjacency matrix is square, but the initialization code is not shown, so it should be checked. The assumption can be removed by making the inner loop condition adj_matrix[v].size() (given a node v) or else if that is an invariant, add an assert before that inner loop: assert( adj_matrix[v].size() == adj_matrix.size() && "adj_matrix is not square!" ); --the same goes for the member size and the size of the adj_matrix it self.
The whole algorithm seems more complex than it should, a DFS starting at node v has the general shape of:
dfs( v )
set visited[ v ]
operate on node (print node label...)
for each node reachable from v:
if not visited[ node ]:
dfs( node )
Your algorithm seems to be (incorrectly by the way) transversing the graph in the opposite direction. You set the given node as visited, and then try to locate any node that is the start point of an edge to that node. That is, instead of following nodes reachable from v, you are trying to get nodes for which v is reachable. If that is the case (i.e. if the objective is printing all paths that converge in v) then you must be careful not to hit the same edge twice or you will end up in an infinite loop -> stackoverflow.
To see that you will end with stackoverlow, consider this example. The start node is 1. You create the visited vector and mark position 1 as visited. You find that there is an edge (0,1) in the tree, and that triggers the if: adj_matrix[0][1] != 0 && visited[1], so you enter recursively with start node being 1 again. This time you don't construct the auxiliary data, but remark visited[1], enter the loop, find the same edge and call recursively...
I see a couple of problems:
The following line
if( adj_matrix[v][x] != 0 && visited[x] != false ) {
should be changed to
if( adj_matrix[v][x] != 0 && visited[x] == false ) {
(You want to recurse only on vertices that have not been visited already.)
Also, you're creating a new variable v in the for loop that hides the parameter v: that's legal C++, but it's almost always a terrible idea.