How to fix segmentation fault with two-dimensional nested vectors - c++

I have written one simple graph Adj Matrix from one Adj List from gitHub .
The first one is Adj list,
Second is Adj matrix.
The first One work well. But the second is wrong with int Num which represent the vertices number like the first one int numOfVertices.
It seed like the 'int Num' become a read only variable. It crash into Process finished with exit code 11 .
I have looked for wiki to find "segmentation default", there are 4 reasons , one of them is trying to modify a read only
variable.
Then I cancel the modify for "Num" in constructor for the Adj Matrix. It work well.
But I don't know why the first one is well but the second is wrong? And how to solve it? Because I need to modify the value of Num...
The Adj List code
#ifndef ALTHGORITHM_GRAPH_ADJ_LIST_H
#define ALTHGORITHM_GRAPH_ADJ_LIST_H
#include <iostream>
#include <vector>
#include <queue>
namespace graph_adj_list {
template <class dataType> // Type of data vertex will hold
class Graph {
int numOfVertices; // number of vertices.
struct Vertex; // forward declaration of vertex structure
struct Node { // linkedlist for mapping edges in the graph
Vertex * vertexPtr; // points to the vertex to which the edge is adjecent
Node * next; // points to the next edge belonging to same vertex
};
enum visitedState{ // Enum representing visited state of vertex
WHITE, // not yet visited
GRAY, // being visited
BLACK // visited
};
struct Vertex {
visitedState state; // state of vertex, visited/being visited/done
dataType data; // the template data
Node * list; // Pointer to all edges (linkedlist)
};
std::vector<Vertex> vertices; // vector of all vertices.
//private methods
Node * getNode( Vertex * ); // allocate and initialize a newnode for the adj list.
void insertAtEnd( Node * & , Vertex * ); // insert at the end of adjacency list of vertex.
void deleteAllAfter( Node * ); // delete the adjacency list of the vertex.
public:
Graph() = default; // Default constructor
Graph(std::vector<dataType> &);
~Graph();
}
template <typename dataType>
typename Graph<dataType>::Node *
Graph<dataType>::getNode(Vertex * v) // allocate and initialize a newnode for the adj list.
{
Node * newNode = new Node;
newNode->vertexPtr = v;
newNode->next = nullptr;
return newNode;
}
template <typename dataType>
void Graph<dataType>::insertAtEnd( Node * & node, Vertex * v) // insert at the end of adjacency list of vertex.
{
Node *newNode = getNode(v);
if ( node == nullptr ) {
node = newNode;
} else {
Node * temp = node;
while( temp->next != nullptr ) {
temp = temp->next;
}
temp->next = newNode;
}
}
template <typename dataType>
void Graph<dataType>::deleteAllAfter( Node * node ) // delete the adjacency list of the vertex.
{
Node * nextNode;
while( node != nullptr ) {
nextNode = node->next;
delete(node);
node = nextNode;
}
}
template <typename dataType>
Graph<dataType>::Graph(std::vector<dataType> & values) // Non default constructor, takes a vector of vertices data
: numOfVertices(values.size()),
vertices(numOfVertices)
{
for ( int i = 0; i < numOfVertices; ++i ) {
vertices[i].data = values[i];
vertices[i].list = nullptr;
vertices[i].state = WHITE;
}
}
template <typename dataType>
Graph<dataType>::~Graph()
{
for( int i = 0; i < numOfVertices; ++i ) {
deleteAllAfter(vertices[i].list);
}
}
} //end of namespace graph
The Adj Matrix code
#ifndef ALTHGORITHM_GRAPH_ADJ_MATRIX_H
#define ALTHGORITHM_GRAPH_ADJ_MATRIX_H
#include <iostream>
#include <vector>
namespace graph_adj_matrix {
template<typename T>
class Graph {
int Num ;
enum visitedState {
NO_VISIT,
VISITING,
VISITED
};
struct vertex {
T data;
visitedState state;
};
std::vector<std::vector<int>> Matrix;
std::vector<vertex> matrix_list;
public:
Graph() = default;
Graph(std::vector<T> &);
~Graph();
void setMatrix(size_t index1, size_t index2);
void display();
};
template<typename T>
Graph<T>::Graph(std::vector<T> &values) :
Num(values.size())
,matrix_list(Num){
for (typename std::vector<T>::size_type i = 0; i < Num; ++i)
{
matrix_list[i].data = values[i];
matrix_list[i].state = NO_VISIT;
}
for (typename std::vector<T>::size_type i = 0; i < Num; ++i)
for (typename std::vector<T>::size_type j = 0; j < Num; ++j)
Matrix[i].push_back(0);
}
template<typename T>
void Graph<T>::setMatrix(size_t index1, size_t index2) {
for (size_t i = 0; i < Num; ++i) {
if (i == index1 || i == index2) {
for (size_t j = 0; j < Num; ++j) {
if (((i == index1) && (j == index2)) || ((i == index2) && (j == index1))) {
Matrix[i][j] = 1;
break;
}
}
break;
}
}
}
template<typename T>
void Graph<T>::display() {
for (size_t i = 0; i < Num; ++i) {
for (size_t j = 0; j < Num; j++)
std::cout << Matrix[i][j] << " ";
std::cout << std::endl;
}
}
template <typename T>
Graph<T>::~Graph() {}
}
#endif //ALTHGORITHM_GRAPH_ADJ_MATRIX_H
Cpp:
#include "Graph_Adj_List.h"
#include "Graph_Adj_Matrix.h"
int main() {
std::vector<std::string> myVec{"ABC","DEF","GHI","ZZZ"};
graph_adj_list::Graph<std::string> myGraph(myVec);
graph_adj_matrix::Graph<std::string> myGraph_matrix(myVec);
}
I have debugger the program
graph_adj_list::Graph<std::string> myGraph(myVec);
work well.
But the
graph_adj_matrix::Graph<std::string> myGraph_matrix(myVec);
stop at
#ifndef _LIBCPP_CXX03_LANG
template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
void
vector<_Tp, _Allocator>::push_back(value_type&& __x)
{
if (this->__end_ < this->__end_cap())
{
__RAII_IncreaseAnnotator __annotator(*this);
__alloc_traits::construct(this->__alloc(),
_VSTD::__to_raw_pointer(this->__end_),
_VSTD::move(__x));
__annotator.__done();
++this->__end_;
}
else
__push_back_slow_path(_VSTD::move(__x));
}
A function from vector header Row from 1635 to 1653.
Debugger report this
Exception = EXC_BAD_ACCESS (code=1, address=0x8)
this = {std::_11::vector<int,std::_1::allocator> * |0x0 } NULL
When I enter the body that sets the ```Matrix[i].push_back(0)''' It crashes the wrong condition.

The following is just an gues, after short playing around with your code:
Process finished with exit code 11
Probably could mean that your program encountered signal 11 (SIGSEGV, aka Segmentation fault)
My guess: you forgot to initialize Matrix, so Matrix[i].push_back(0); causes undefined behaviour and luckily resultet in a segmentation fault.
Edit: you can easily initialize the inner vectors with the vector constructor: std::vector<std::vector<int>>(Num, std::vector<int>(Num));. This will create a vector with Num copies of a vector with Num ints.

After having fixed the problem that #churill proposed:
I haven't compiled your code, but I think the problem lies on these lines:
Matrix[i][j] = 1;
In this case Matrix[i] is a vector<int>, but you never reserve capacity for it, so Matrix[i][j] is writing to protected / unallocated memory, causing the segfault.
Initialize your "internal" vectors (all Matrix[i]) with sufficient capacity and see if that resolves your segfault.

Related

Breadth / Depth First Search causes crash when run on graph for second time

So I have a directed graph which I have added vertices and edges to. The graph represents airports and flights between them. When I run a breadth First or a Depth First search to find a path between two airports I get the correct answer the first time, but when I run it the second time with the exact same airports it cannot find a path and the program crashes with error code -1073741819. I've been trying to figure this out for hours and I'm stumped.
I ran the debugger and the problem seems to occur when the BFS algorithm goes into the IsMarked() function of the graph. It can't read the vertices[] array and the debugger says
Here is my graph class
#pragma once
#include "queue.h"
const int NULL_EDGE = 0;
template<class VertexType>
class GraphType
{
public:
GraphType(); // constructor, default of 50 vertices.
GraphType(int maxV); // parameterized constructor, maxV <= 50.
~GraphType(); // destructor
void MakeEmpty();
bool IsEmpty() const;
bool IsFull() const;
void AddVertex(VertexType);
void AddEdge(VertexType, VertexType, int);
int WeightIs(VertexType, VertexType);// (fromVertex, toVertex).
void GetToVertices(VertexType, QueType<VertexType>&);
void ClearMarks();
void MarkVertex(VertexType);
bool IsMarked(VertexType) const;
void DisplayFlights();
private:
int numVertices;
int maxVertices;
VertexType* vertices;
int edges[50][50];
bool* marks; // marks[i] is mark for vertices[i].
};
template<class VertexType>
GraphType<VertexType>::GraphType()
// Post: Arrays of size 50 are dynamically allocated for
// marks and vertices. numVertices is set to 0;
// maxVertices is set to 50.
{
numVertices = 0;
maxVertices = 50;
vertices = new VertexType[50];
marks = new bool[50];
//ClearMarks();
}
template<class VertexType>
GraphType<VertexType>::GraphType(int maxV)
// Post: Arrays of size maxV are dynamically
// allocated for marks and vertices.
// numVertices is set to 0; maxVertices is set to maxV.
{
numVertices = 0;
maxVertices = maxV;
vertices = new VertexType[maxV];
marks = new bool[maxV];
//ClearMarks();
}
template<class VertexType>
GraphType<VertexType>::~GraphType()
// Post: arrays for vertices and marks have been // deallocated.
{
delete[] vertices;
delete[] marks;
}
template<class VertexType>
void GraphType<VertexType>::MakeEmpty()
{
//not yet coded
}
template<class VertexType>
bool GraphType<VertexType>::IsEmpty() const
{
return (numVertices == 0);
}
template<class VertexType>
bool GraphType<VertexType>::IsFull() const
{
return (numVertices == maxVertices);
}
template<class VertexType>
void GraphType<VertexType>::AddVertex(VertexType vertex)
// Post: vertex has been stored in vertices.
// Corresponding row and column of edges have been
// set to NULL_EDGE.
// numVertices has been incremented.
{
//Not allowed to add duplicate vertex
bool duplicate = false;
for (int i = 0; i < numVertices; i++) {
if (vertices[i] == vertex)
duplicate = true;
}
if (!duplicate) {
vertices[numVertices] = vertex;
for (int index = 0; index < numVertices; index++)
{
edges[numVertices][index] = NULL_EDGE;
edges[index][numVertices] = NULL_EDGE;
}
numVertices++;
}
else {
cerr << "Cannot add duplicate vertex\n";
}
}
template<class VertexType>
int IndexIs(VertexType * vertices,VertexType vertex)
// Post: Function value = index of vertex in vertices.
{
int index = 0;
while (!(vertex == vertices[index]))
index++;
return index;
}
template<class VertexType>
void GraphType<VertexType>::AddEdge(VertexType fromVertex,VertexType toVertex, int weight)
// Post: Edge (fromVertex, toVertex) is stored in edges.
{
/*int row;
int column;*/
int row = IndexIs(vertices, fromVertex);
int col = IndexIs(vertices, toVertex);
edges[row][col] = weight;
}
template<class VertexType>
int GraphType<VertexType>::WeightIs(VertexType fromVertex,VertexType toVertex)
// Post: Function value = weight associated with the
// edge (fromVertex, toVertex).
{
/*int row;
int column;*/
int row = IndexIs(vertices, fromVertex);
int col = IndexIs(vertices, toVertex);
return edges[row][col];
}
template<class VertexType>
void GraphType<VertexType>::GetToVertices(VertexType vertex, QueType<VertexType>& adjvertexQ)
{
int fromIndex;
int toIndex;
fromIndex = IndexIs(vertices, vertex);
for (toIndex = 0; toIndex < numVertices; toIndex++)
if (edges[fromIndex][toIndex] != NULL_EDGE)
adjvertexQ.Enqueue(vertices[toIndex]);
}
template<class VertexType>
void GraphType<VertexType>::ClearMarks()
{
for (int i = 0; i < maxVertices; i++) {
marks[i] = false;
}
}
template<class VertexType>
void GraphType<VertexType>::MarkVertex(VertexType vertex)
{
for (int i = 0; i < numVertices; i++) {
if (vertex == vertices[i]) {
marks[i] = true;
break;
}
}
/*int index = 0;
while (!(vertex == vertices[index])) {
if (vertex == vertices[index]) {
marks[index] = true;
index++;
}
}*/
}
template<class VertexType>
bool GraphType<VertexType>::IsMarked(VertexType vertex) const
{
for (int i = 0; i < numVertices; i++) {
if (vertices[i] == vertex) {
return marks[i];
}
}
}
template<class VertexType>
void GraphType<VertexType>::DisplayFlights()
{
//foreach vertex
QueType<VertexType> q;
VertexType adjVertex;
int weight;
for (int i = 0; i < numVertices; i++) {
GetToVertices(vertices[i], q);
//get adjacent vertices
while (!q.IsEmpty()) {
q.Dequeue(adjVertex);
weight = WeightIs(vertices[i], adjVertex);
cout << vertices[i] << " to " << adjVertex << " " << weight << endl;
}
}
}
And my Breadth First Search
void BreadthFirstSearch(GraphType<string> graph, string startVertex, string endVertex)
// Assumes VertexType is a type for which the “==“ and “<<“
// operators are defined.
{
QueType<string> queue;
QueType<string> vertexQ;
bool found = false;
string vertex;
string item;
graph.ClearMarks();
queue.Enqueue(startVertex);
do
{
queue.Dequeue(vertex);
if (vertex == endVertex)
{
cout << vertex;
found = true;
}
else
{
if (!graph.IsMarked(vertex))
{
graph.MarkVertex(vertex);
cout << vertex << " ";
graph.GetToVertices(vertex, vertexQ);
while (!vertexQ.IsEmpty())
{
vertexQ.Dequeue(item);
if (!graph.IsMarked(item))
queue.Enqueue(item);
}
}
}
} while (!queue.IsEmpty() && !found);
if (!found)
cout << "Path not found." << endl;
}
Would really appreciate any help. Thank you very much.
In void BreadthFirstSearch(GraphType<string> graph, string startVertex, string endVertex) you pass GraphType<string> by value, meaning, a temporary copy is created. There the pointers vertices and marks are copied too, but not the values they are pointing to.
So the original and temporary object have pointers that point to the same memory locations.
At the end of BreadthFirstSearch the temporary objects gets destroyed. In the destructor you delete[] vertices and marks.
Now the pointers in the original object point to deallocated memory, which causes undefined behaviour.
The easiest solution would be to pass GraphType<string> by reference:
void BreadthFirstSearch(GraphType<string> &graph, string startVertex, string endVertex)
But to be safe it is highly recommended and best practice to use std::vector instead of doing manual memory management.
The problem is that once you have executed your algorithm once the graph ends up with lots of marked vertices. You need to clear the marks for a second execution.

How do I implement vector reallocation?

I am attempting to implement my own version of a C++ vector, but I'm having issues with my reallocation function when the size becomes equal to the capacity. Specifically, when the debugger reaches the delete line, I am given a heap corruption error stating that the application wrote to memory after the end of the heap buffer. Could someone give advice on why my approach is wrong? Please let me know if there is any other information needed that would be helpful in solving this issue.
EDIT: I have added all of my current code so that others can test the program and reproduce the issue.
Header file:
#ifndef VECTOR_H
#define VECTOR_H
template <class ItemType> class Vector{
public:
Vector();
Vector(int capacity);
int size();
int capacity();
bool is_empty();
ItemType at(int index);
void push(ItemType newItem);
void printItems();
~Vector();
private:
int m_capacity; // number of items we can hold
int m_size; // current number of items
int m_unitSize; // size of one unit (used for arithmetic in indexing)
ItemType* m_vectorPtr; // pointer to actual vector
void reallocate(); // reallocates memory if array is filled
};
#endif
Implementations and testing:
#include <iostream>
#include "Vector.h"
#include <assert.h>
// default constructor
template <class ItemType>
Vector<ItemType>::Vector()
:m_capacity(0), m_size(0) {
m_unitSize = sizeof(ItemType);
m_vectorPtr = nullptr;
}
// constructor with given number of items
template <class ItemType>
Vector<ItemType>::Vector(int capacity)
:m_size(0){
int x = 1;
while (x <= capacity) {
x *= 2;
}
m_unitSize = sizeof(ItemType);
m_capacity = x;
m_vectorPtr = new ItemType[capacity];
}
// return total possible items
template <class ItemType>
int Vector<ItemType>::capacity() {
return m_capacity;
}
// return current number of elements
template <class ItemType>
int Vector<ItemType>::size() {
return m_size;
}
// return whether the vector is currently empty
template <class ItemType>
bool Vector<ItemType>::is_empty() {
return m_size == 0;
}
// return the item at a given index
template<class ItemType>
ItemType Vector<ItemType>::at(int index) {
return m_vectorPtr[index];
}
// reallocate the array if it becomes full
template <class ItemType>
void Vector<ItemType>::reallocate() {
if (m_size >= m_capacity) {
// allocate a new array twice the capacity
m_capacity *= 2;
ItemType* newVector = new ItemType[m_capacity];
for (int i = 0; i < m_size; i++) {
newVector[i] = m_vectorPtr[i];
}
delete[] m_vectorPtr;
m_vectorPtr = newVector;
}
}
// push an item onto the vector at the end
template<class ItemType>
void Vector<ItemType>::push(ItemType newItem) {
if (m_size >= m_capacity) {
// reallocate memory for the vector
reallocate();
}
// push new item onto vector
m_vectorPtr[m_size] = newItem;
m_size++;
}
template <class ItemType>
void Vector<ItemType>::printItems() {
for (int i = 0; i < m_size; i++) {
std::cout << m_vectorPtr[i] << " ";
}
std::cout << std::endl;
}
template <class ItemType>
Vector<ItemType>::~Vector() {
delete[] m_vectorPtr;
}
// test here
int main() {
// initialize a vector
int startingCapacity = 3;
Vector<int> testVector(startingCapacity);
assert(testVector.capacity() == 4 &&
testVector.size() == 0 &&
testVector.is_empty() == true);
// add two items to the vector
testVector.push(3);
testVector.push(7);
assert(testVector.capacity() == 4 &&
testVector.size() == 2 &&
testVector.is_empty() == false);
// print the two items
testVector.printItems();
// add past capacity to test reallocate
testVector.push(5);
testVector.push(8);
testVector.push(6);
assert(testVector.capacity() == 8 &&
testVector.size() == 5 &&
testVector.is_empty() == false);
testVector.printItems();
std::cout << "All test cases passed." << std::endl;
return 0;
}
You have to reallocate before you change m_size because the for loop will be incorrect if m_size > m_capacity and you'll access m_vectorPtr past its size. And make sure the new capacity is big enough (m_capacity *= 2) > new_size
template <class ItemType>
void Vector<ItemType>::reallocate(size_t new_size) {
if (new_size > m_capacity) {
// allocate a new array twice the capacity
if (m_capacity == 0)
m_capacity = 10;
while (m_capacity < new_size)
m_capacity *= 2;
ItemType* newVector = new ItemType[m_capacity];
for (int i = 0; i < m_size; i++) {
newVector[i] = m_vectorPtr[i];
}
delete[] m_vectorPtr;
m_vectorPtr = newVector;
}
}
And here sample push_back method reallocating before changing m_size:
void push_back(ItemType item) {
reallocate(m_size + 1);
m_vectorPtr[m_size] = item;
m_size++;
}
Demo
UPDATE
You have a small bug in the constructor NOT:
m_vectorPtr = new ItemType[capacity];
but
m_vectorPtr = new ItemType[m_capacity];
because capacity is the requested one, not the power of two you want (3, not 4 in your test).

C++ structures containing structures SIGSEGV

Let me paste the code first
#include <iostream>
#include <algorithm>
#define MAX 100
using namespace std;
int index;
struct node{
int key;
struct node *up;
int rank;
};
struct edge{
struct node *start, *end;
int weight;
};
struct graf{
struct node *tops[MAX];
int topsAmount;
struct edge *edges[MAX];
int edgesAmount;
};
void makeSet(struct node *z, int key){
z->up = z;
z->rank = 0;
z->key = key;
}
struct node *findSet(struct node *x){
if(x!=x->up)
x->up = findSet(x->up);
return x->up;
};
struct node *returnPath(struct node *x){
cout<<"klucz: "<<x->key<<" ranga: "<<x->rank<<endl;
if(x!=x->up)
{
returnPath(x->up);
}
}
void link(struct node *x, struct node *y){
if(x->rank>y->rank)
{
y->up=x;
}
else
{
x->up=y;
if(x->rank == y->rank)
y->rank++;
}
}
void unionFun(struct node *x, struct node *y){
link(findSet(x), findSet(y));
}
bool acompare(edge lhs, edge rhs) { return lhs.weight < rhs.weight; }
struct edge *MSTKruskal(struct graf *G){
struct edge *A = new edge[MAX];
index=0;
for(int i=0; i<G->topsAmount; i++)
{
makeSet(G->tops[i],0);
}
sort(G->edges[0], G->edges[G->edgesAmount-1], acompare);
for(int i=0; i<G->edgesAmount; i++)
{
if(findSet(G->edges[i]->start) != findSet(G->edges[i]->end))
{
A[index].start = G->edges[i]->start;
A[index].end = G->edges[i]->end;
A[index].weight = G->edges[i]->weight;
index++;
unionFun(G->edges[i]->start, G->edges[i]->end);
}
}
return A;
}
int main()
{
struct node *values[11];
for(int i=0; i<10; i++)
{
values[i] = new node;
makeSet(values[i],i);
}
unionFun(values[0], values[1]);
unionFun(values[2], values[3]);
unionFun(values[1], values[2]);
unionFun(values[5], values[6]);
unionFun(values[7], values[8]);
unionFun(values[3], values[5]);
unionFun(values[0], values[7]);
for(int i=0; i<10; i++)
{
cout<<"sciezka klucza "<<i<<endl;
returnPath(values[i]);
}
struct graf *Graf = new graf;
for(int i=0; i<10; i++)
{
Graf->tops[i] = values[i];
Graf->topsAmount++;
}
struct edge *Edges = new edge[4];
Edges[0].start = values[1];
Edges[1].start = values[2];
Edges[2].start = values[3];
Edges[3].start = values[4];
Edges[0].end = values[5];
Edges[1].end = values[6];
Edges[2].end = values[7];
Edges[3].end = values[8];
Edges[0].weight = 10;
Edges[1].weight = 12;
Edges[2].weight = 11;
Edges[3].weight = 13;
Graf->edges[0] = Edges[0]; //this line was deleted after I found out that I can't compile it
Graf->edges[0]->weight = 0;
return 0;
}
I want to set new graf so firstly in for loop I add tops to my structure and it works then I want to add edges and problem appears. I thought I can just create another array of structures edge and then just set same array in Graf on same values (Graf->edges[0] = Edges[0]; last lines of the code) but it didn't compile, so I wanted to set every value of structure edge in array Graf separately (start = start, end = end etc) but debugger shows SIGSEGV on last line (Graf->edges[0]->weight = 0;) how can I fix it?
Edges[0] has type edge, but Graf->edges[0] has type edge*, i.e. the types are incompatible, which is why the assignment is not allowed.
You probably want to take the address of Edges[0] like so:
Graf->edges[0] = &Edges[0];

Determining stack size in iterative depth first search (DFS) algorithm

I have written an iterative implementation of depth first search (DFS) algorithm in C++. It produces correct visiting order as output. Algorithm goes like that:
Initiate visited[] array with false values.
Push first vertex into stack.
Pop element from stack and assign it to variable v.
If v was not visited (visited[v] == false), print v and set it as visited.
Push every not visited neighbors of v into stack (biggest value first).
Repeat 3-5 until stack is empty.
The problem I have is to determine proper Stack s size in DFSIteratively method of GraphUtilities class. My teacher stated it has to be stored as array. I am able to calculate it's size using (n * n - 3 * n + 2) / 2 equation, where n is vertex set count, assuming no visited vertex is ever pushed into stack and full graph was provided (most dense graph; pessimistic case).
Can stack size be determined for factual graph, which most likely will not be a full graph? Or, better yet, is there a way to push every vertex into stack only once? I know recursive implementations solves this limitation, as well as using dynamic data struct as stack, but my project assumes using array (educational purposes, that's what I was told).
#include <iostream>
#include <stdexcept>
#include <list>
#include <sstream>
#include <fstream>
#include <cstdlib>
using namespace std;
template <typename T> class Stack
{
private:
int ptr;
T *stackArray;
int stackSize;
public:
Stack(int n)
{
ptr = -1;
stackSize = n;
stackArray = new T[stackSize];
}
~Stack()
{
delete[] stackArray;
}
void push(T x)
{
if(ptr + 1 == stackSize)
throw length_error("Cannot push.");
stackArray[++ptr] = x;
}
T top()
{
if(ptr == -1)
throw length_error("Cannot pop.");
return stackArray[ptr];
}
T pop()
{
T temp = top();
ptr--;
return temp;
}
bool isEmpty()
{
if(ptr == -1)
return true;
return false;
}
};
class Graph
{
private:
int numberOfVertices;
list<int> *adjacencyList;
public:
Graph(int n)
{
numberOfVertices = n;
adjacencyList = new list<int>[numberOfVertices];
}
int getNumberOfVertices()
{
return numberOfVertices;
}
list<int>* getAdjacencyList(int v)
{
return &adjacencyList[v];
}
list<int>* getAdjacencyList()
{
return adjacencyList;
}
~Graph()
{
delete[] adjacencyList;
}
void addEdge(int v1, int v2)
{
adjacencyList[v1].push_back(v2);
}
};
class GraphUtilities
{
private:
bool *visited;
stringstream visitingOrder;
public:
void DFSIteratively(Graph &g, int v)
{
int n = g.getNumberOfVertices();
list<int> *adjacencyList = g.getAdjacencyList();
visited = new bool[n];
Stack<int> *s;
// Determine size of stack.
if(n == 1)
s = new Stack<int>(1);
else
s = new Stack<int>( (n*n - 3*n + 2)/2 );
for(int i = 0; i < n; i++)
visited[i] = false;
s -> push(v);
while(!(s -> isEmpty()))
{
v = s -> pop();
if(!visited[v])
{
visitingOrder << v << " ";
visited[v] = true;
for(list<int>::reverse_iterator i = adjacencyList[v].rbegin(); i != adjacencyList[v].rend(); ++i)
if(!(visited[*i]))
s -> push(*i);
}
}
cout << visitingOrder.str() << endl;
visitingOrder.clear();
delete[] visited;
delete s;
}
};
int main()
{
Graph graph(6);
GraphUtilities utilities;
graph.addEdge(0, 1);
graph.addEdge(0, 2);
graph.addEdge(0, 4);
graph.addEdge(1, 0);
graph.addEdge(1, 5);
graph.addEdge(2, 0);
graph.addEdge(2, 5);
graph.addEdge(3, 5);
graph.addEdge(4, 0);
graph.addEdge(5, 1);
graph.addEdge(5, 2);
graph.addEdge(5, 3);
utilities.DFSIteratively(graph, 4);
return 0;
}
My graph (paint quality): http://i.imgur.com/pkGKNFo.jpg
Output:
4 0 1 3 5 2
Probably you might be happier if you'll use additional addedToStack flag array of size n next to your visited array. So if you'll add a vertex to stack it will not be visited but added to stack. There is no need in adding it to the stack again. Check addedToStack flag each time you want to add a vertex to the stack. Eventually every vertex will occur in the stack not more than once and the stack size will be n at most.

Array resize function in dynamic memory

I'm making a function to resize an array in dynamic memory and it's not working..
here's the code:
template <class Type>
void Array<Type>::Resize(int newSize)
{
if(newSize==size)
return;
if(newSize<=0)
return;
Type *temp = new Type[newSize];
int min=(newSize>size)?size:newSize;
for(int i=0; i<min; i++)
temp[i]=elements[i];
delete []elements;
elements = temp;
temp = NULL;
}
the problem is in these two statements
delete []elements;
elements = temp;
cause when i comment them the program works properly,
but it actually doesn't do what is supposed to do..
I think the problem is something that is being destroyed when getting out of the function scope and I have to call it by reference but I can't actually cause this is a member function.
Here's the whole header file:
#include<string>
#include<iostream>
using namespace std;
#ifndef ARRAY_H
#define ARRAY_H
template <class Type>
class Array
{
public:
Array (int s);
Array (const Array& obj);
~Array ();
const Array& operator= (const Array& obj);
Type GetElement (int index) const;
void SetElement (Type ele, int index);
void Resize (int newSize);
void Print () const;
void Destroy ();
private:
int size;
Type* elements;
};
template <class Type>
Array<Type>::Array(int s)
{
if(s<0)
return;
size=s;
elements = new Type[size];
}
template <class Type>
Array<Type>::Array(const Array &obj)
{
size = obj.size;
elements = new Type[size];
for(int i=0; i<size; ++i)
elements[i]=obj.elements[i];
}
template <class Type>
Array<Type>::~Array()
{
delete [] elements;
elements = NULL;
size = 0;
}
template <class Type>
void Array<Type>::Destroy()
{
delete [] elements;
elements = NULL;
size = 0;
}
template <class Type>
const Array<Type> &Array<Type>::operator=(const Array &obj)
{
if(this != &obj)
{
size = obj.size;
if(elements != NULL)
delete [] elements;
elements = new Type[size];
for(int i=0; i<size; i++)
elements[i] = obj.elements[i];
}
return *this;
}
template <class Type>
Type Array<Type>::GetElement(int index) const
{
if(index<0 || index>=size)
cout << "Sorry, this operation can not be proceeded \n";
else
return elements[index];
}
template <class Type>
void Array<Type>::SetElement(Type ele, int index)
{
if(index<0 || index>=size){
cout << "Sorry, this operation can not be proceeded \n";
return; }
else
elements[index] = ele;
}
template <class Type>
void Array<Type>::Print() const
{
for(int i=0;i<size; ++i)
cout << elements[i] << endl;
}
template <class Type>
void Array<Type>::Resize(int newSize)
{
if(newSize==size)
return;
if(newSize<=0)
return;
Type *temp = new Type[newSize];
int min=(newSize>size)?size:newSize;
for(int i=0; i<min; i++)
temp[i]=elements[i];
delete []elements;
elements = temp;
temp = NULL;
}
#endif
You forgot to do one thing in the Resize() function, and that is to update the member size with the new size after reallocation. This will cause it to access memory beyond the end of the buffer after a resize with a smaller new dimension, e.g.:
Array<int> arr(10);
// set the 10 values
arr.Resize(5);
// here the buffer will have 5 elements, but arr.size is still 10
arr.Print(); // this will read elements 0 - 9, not 0 - 4
Couple of observations
if(newSize==size)
size does not exist
delete []elements;
elements = temp;
You are attempting to copy to an array you have just deleted, which was never created in the first place.
What is meant by "does not work" and "the program works properly,"?