I have implemented a stack using the next class:
template <typename T, int lungime> class Depou
{
private:
T *depouarray;
int top;
public:
Depou ()
{
this -> top = -1;
depouarray = (T *) calloc (lungime, sizeof (T));
}
~Depou ()
{
free (depouarray);
}
void push (T x)
{
if (top >= lungime - 1)
{
return;
}
top ++;
depouarray [top] = x;
}
T pop ()
{
if (isEmpty ())
{
return -1;
}
T x;
x = depouarray [top];
top --;
return x;
}
T peek ()
{
if (isEmpty ())
{
return -1;
}
return depouarray[top];
}
int isEmpty ()
{
return (top < 0);
}
}
My problem is the next one:
After I've added an element to the stack, let's say 3, I verified it and it showed 3.
Next, I added another element, let's say 4, I verified the content of the stack and it showed a very high number (which is surely junk) and 4. I cannot understand why it transforms the first elements into junk, leaving only the last element added as it should be.
As my colleague pointed out, you have many errors within your code and I think i t would be too much effort to correct it. Hence I'm giving you a stack implementation.
A stack is a FILO structure. The best way to implement it is to use Node and to link them together. Look at the code below, it is straight forward. Let me know if you have questions.
template <class T>
class Stack {
public:
Stack();
~Stack();
void push(const T&);
void pop(T& out);
T pop();
bool is_empty() const;
void clear();
private:
class Node {
public:
Node(const T& t, Node* c);
T contain;
Node* next;
};
Node* peak;
};
template <class T>
Stack<T>::Stack()
{
peak = NULL;
}
template <class T>
Stack<T>::~Stack()
{
clear();
}
template <class T>
bool Stack<T>::is_empty() const
{
return peak == NULL;
}
template <class T>
void Stack<T>::clear()
{
while(!is_empty())
pop();
}
template <class T>
Stack<T>::Node::Node(const T& t, Node* c) : next(c)
{
contain = t;
}
template <class T>
void Stack<T>::push(const T& t)
{
peak = new Node(t, peak);
assert(peak);
}
template <class T>
T Stack<T>::pop()
{
assert(peak);
Node c(*peak);
delete peak;
peak = c.next;
return c.contain;
}
template <class T>
void Stack<T>::pop(T& t)
{
assert(peak != NULL);
t = peak->contain;
Node* c = peak;
peak = peak->next;
delete c;
}
Related
i made some code about stack using template.
but right now, stuck with the little error.
i tried many times as i can but don't know what to do.
also, i see the a lot of same error question but my one is seems to be different.
I'm middle of the writing.
so, there is some uncompleted code.
if you see something wrong but not cause the error, ignore it please.
#ifndef STACKINTERFACE_H
#define STACKINTERFACE_H
using namespace std;
template <typename T>
class StackInterface {
public:
StackInterface() {};
virtual ~StackInterface() {};
virtual bool isEmpty() const = 0;
virtual bool isFull() const = 0;
virtual void push(T data) = 0;
virtual void pop() = 0;
virtual T top() const = 0;
};
#include "StackInterface.h"
#include <iostream>
template <typename T>
class Stack : public StackInterface {
private:
T * items;
const static int max = 10;
const static int GROWBY = 5;
size_t arrayCapacity;
size_t numItems;
int top_position;
public:
Stack();
virtual void push(T data);
virtual T top() const;
virtual void pop();
virtual bool isEmpty() const;
virtual bool isFull() const;
size_t getArrayCapacity();
size_t getNumItems();
Stack<T> operator=(const Stack<T>&Other);
~Stack();
Stack(const Stack<T>& other);
};
template <typename T>
Stack<T>::Stack()
{
items = new T[max];
numItems = 0;
top_position = -1;
}
template <typename T>
Stack<T>::~Stack() {
cout << "deleting..." << endl;
delete[] items;
}
template <typename T>
void Stack<T>::push(T data) {
cout << "inserting" << data << endl;
if (numItems < arrayCapacity) {
T[++top_position] = data;
}
numItems++;
}
template <typename T>
void Stack<T>::pop() {
if (isEmpty) {
cout << "The stack is empty. Returned value not reliable.\n";
}
else {
cout << "removing" << top() << endl;
retrun T[top_position--];
}
}
template <typename T>
bool Stack<T>::isEmpty() const
{
if (numItems == 0) {
return true;
}
else {
return false;
}
}
template <typename T>
bool Stack<T>::isFull() const
{
if (numItems == max) {
return true;
}
else {
return false;
}
}
template <typename T>
T Stack<T>::top() const
{
if (!isEmpty()) {
return T[top_position];
}
else {
throw exception;
}
}
template <typename T>
Stack <T> Stack<T>:: operator=(const Stack<T>&Other) {
if (&Other == this) {
return *this;
}
}
template <typename T>
Stack<T>::Stack(const Stack<T>& other) {
items = new items(other.items);
numItems = other.numItems;
top_position = other.top_position;
arrayCapacity = other.arrayCapacity;
}
template <typename T>
size_t Stack<T>::getArrayCapacity() {
return arrayCapacity;
}
template <typename T>
size_t Stack<T>::getNumItems() {
return numItems;
}
int main() {
Stack <int> S1;
system("pause");
return 0;
}
You need to give template arguments to your superclass. Instead of this:
template <typename T>
class Stack : public StackInterface {
Do this:
template <typename T>
class Stack : public StackInterface<T> {
(There's lots of other problems with your code too, but that's how you fix the specific one you asked about.)
I've created a simple dynamic template list and i'm having some issue clearing the entire list.
List.h
#ifndef LIST_H
#define LIST_H
#include <Node.h>
template <class T> class List
{
public:
typedef Node<T> node_type;
typedef node_type* node_pointer;
typedef T data_type;
typedef T& reference_type;
List();
void push_back(data_type);
reference_type at(int);
void clear();
void swap(int,int);
int size();
private:
int list_size = 0;
node_pointer head, tail;
};
template <class T> List<T>::List()
{
head=NULL;
tail=NULL;
}
template <class T> void List<T>::push_back(data_type data)
{
if(head == NULL) {
head = new node_type(data);
tail = head;
} else {
node_pointer temp = new node_type(data);
temp->setNextNull();
tail->setNext(temp);
tail = tail->getNext();
}
list_size++;
}
template <class T> typename List<T>::reference_type List<T>::at(int x)
{
node_pointer pointer=head;
for(int i=0; i<x; i++)
pointer=pointer->getNext();
return pointer->getData();
}
template <class T> void List<T>::clear()
{
node_pointer pointer = head;
for(int i=0; i<list_size; i++) {
node_pointer temp = pointer;
pointer=pointer->getNext();
delete(temp);
}
head=NULL;
list_size=0;
}
template <class T> void List<T>::swap(int x, int y)
{
data_type buffer=at(x);
at(x)=at(y);
at(y)=buffer;
}
template <class T> int List<T>::size()
{
return list_size;
}
#endif // LIST_H
Node.h
template <class T> class Node
{
public:
typedef T data_type;
typedef T& reference_type;
Node(data_type _data);
void setData(data_type);
void setNextNull();
void setNext(Node*);
reference_type getData();
Node* getNext();
private:
data_type data;
Node* next;
};
template <class T> Node<T>::Node(data_type _data) : data(_data)
{
setNextNull();
}
template <class T> void Node<T>::setData(data_type _data)
{
data=_data;
}
template <class T> void Node<T>::setNextNull()
{
next=NULL;
}
template <class T> void Node<T>::setNext(Node* _next)
{
next=_next;
}
template <class T> typename Node<T>::reference_type Node<T>::getData()
{
return data;
}
template <class T> typename Node<T>::Node* Node<T>::getNext()
{
return next;
}
If I clear the list calling the "clear" method I get all sorts of errors in almost every other method, but if I use the version below the list works perfectly.
template <class T> void List<T>::clear()
{
head=NULL;
tail=NULL;
list_size=0;
}
The problem only appears if I use the delete function to clear memory. How can I solve this issue?
Your code is very dangerious, because you skipped important checks. Try to use following implementation of at():
template <class T> typename List<T>::reference_type List<T>::at(int x)
{
if (x < 0 || x >= list_size || list_size <= 0)
return DATA_WITH_ERROR_FLAG; // since you return data instead of pointer,
// you can't return NULL here
// (you need special constant for error status
// or support it another way)
node_pointer pointer=head;
for(int i=0; i<x; i++)
{
if (!pointer)
return DATA_WITH_ERROR_FLAG;
pointer=pointer->getNext();
}
if (!pointer)
return DATA_WITH_ERROR_FLAG;
return pointer->getData();
}
After it you have to add checks after each at() call. For example, you have to modify swap() to make it safe too:
template <class T> void List<T>::swap(int x, int y)
{
data_type v1=at(x);
data_type v2=at(y);
if (v1 == DATA_WITH_ERROR_FLAG || v2 == DATA_WITH_ERROR_FLAG)
return; // and somehow set error flag!
data_type t=v1;
v1 = v2;
v2 = t;
}
I.e. you need to check correctness everywhere if you don't like such problems. And it is necessary to support returninig of error status to simplify analysis of errors.
Change your clear() method to this:
template <class T> void List<T>::clear()
{
node_pointer pointer = head;
while (pointer != NULL) {
node_pointer temp = pointer-getNext();
delete pointer;
pointer = temp;
}
head=NULL;
tail=NULL;
list_size=0;
}
You have a memory leak in your code. You don't delete all the list by simply pointing head and tail to NULL.
The best way to do this is to create a delete() function then loop through the whole list while it is not empty and delete node by node.
void deleteHead()
{
if(head != NULL)
{
node *temp = head;
head = head->next;
delete temp;
size--;
}
}
bool isEmpty()
{
return head==NULL;
//return size == 0; <-- this is ok as well.
}
void clear()
{
while(! isEmpty())
{
deleteHead();
}
tail = head; //head = NULL
}
I have this implementation of queue:
#include<iostream>
using namespace std;
template <typename T>
struct elem_q
{
T inf;
elem_q<T>* link;
};
template <typename T = int>
class Queue
{
public:
Queue();
~Queue();
Queue(const Queue&);
Queue& operator= (const Queue&);
bool empty()const;
void push(const T&);
void pop(T&);
void head(T&) const;
void print();
int length();
private:
elem_q<T> *front;
elem_q<T> *rear;
void copyQueue(const Queue<T>);
void deleteQueue();
};
template <typename T>
Queue<T>::Queue()
{
front = rear = NULL;
}
template <typename T>
Queue<T>::~Queue()
{
deleteQueue();
}
template <typename T>
Queue<T>::Queue(const Queue<T>& r)
{
copyQueue(r);
}
template <typename T>
Queue<T>& Queue<T>::operator=(const Queue<T>& r)
{
if(this != &r)
{
deleteQueue();
copyQueue(r);
}
return *this;
}
template <typename T>
void Queue<T>::copyQueue(const Queue<T> r)
{
front = rear = NULL;
elem_q<T> *p = r.front;
while(p)
{
push(p->inf);
p = p->link;
}
}
template <typename T>
void Queue<T>::deleteQueue()
{
T x;
while (!empty())
{
pop(x);
}
}
template <typename T>
bool Queue<T>::empty() const
{
return rear == NULL;
}
template <typename T>
void Queue<T>::push(const T& x)
{
elem_q<T> *p = new elem_q<T>;
p->inf = x;
p->link = NULL;
if (rear) rear->link = p;
else front = p;
rear = p;
}
template <typename T>
void Queue<T>::pop(T& x)
{
if(empty())
{
cout<<"The queue is empty.\n";
}
else
{
elem_q<T> *q = front;
x = q->inf;
if (q == rear)
{
rear = NULL;
front = NULL;
}
else front = q->link;
delete q;
}
}
template <typename T>
void Queue<T>::head(T& x) const
{
if(empty())
{
cout<<"The queue is empty.\n";
}
else
{
x = front->inf;
}
}
template <typename T>
void Queue<T>::print()
{
T x;
while(!empty())
{
pop(x);
cout<<x<<" ";
}
cout<<endl;
}
template <typename T>
int Queue<T>::length()
{
T x;
int n = 0;
while(!empty())
{
pop(x);
n++;
}
return n;
}
template<typename T>
void minqueue(Queue<T> q,T& min,Queue<T>& newq)
{
T x;
q.pop(min);
while (!q.empty())
{
q.pop(x);
if (x < min)
{
newq.push(min);
min = x;
}
else newq.push(x);
}
}
template<typename T>
void sortQueue(Queue<T> q,Queue<T>& newq)
{
while(!q.empty())
{
T min;
Queue<T> q1;
minqueue(q , min ,q1);
newq.push(min);
q = q1;
}
}
template<typename T>
Queue<T> merge(Queue<T> p,Queue<T> q,const T& dummy)
{
p.push(dummy);
q.push(dummy);
Queue<T> r;
T x,y;
p.pop(x);
q.pop(y);
while (!p.empty() && !q.empty())
if (x < y)
{
r.push(x);
p.pop(x);
}
else
{
r.push(y);
q.pop(y);
}
if (!p.empty())
do
{
r.push(x);
p.pop(x);
}while (x != dummy);
else
do
{
r.push(y);
q.pop(y);
}while (y != dummy);
return r;
}
How can i redefine operator < and != because without them function minqueue,Sortqueue and merge do not work?Please help me...............................................
template <typename T>
struct elem_q
{
T inf;
elem_q<T>* link;
};
template <typename T>
bool operator <( const elem_q<T> &lhs, const elem_q<T> &rhs )
{
return ( lhs.inf < rhs.inf );
}
template <typename T>
bool operator ==( const elem_q<T> &lhs, const elem_q<T> &rhs )
{
return ( lhs.inf == rhs.inf );
}
template <typename T>
bool operator !=( const elem_q<T> &lhs, const elem_q<T> &rhs )
{
return ( !( lhs.inf == rhs.inf ) );
}
See how you already did this:
template <typename T>
Queue<T>& Queue<T>::operator=(const Queue<T>& r)
{
if(this != &r)
{
deleteQueue();
copyQueue(r);
}
return *this;
}
Overload the other operators you need, too.
Well, logical operators have rather expected syntax, looking like this:
bool ClassName::operator!=(const ClassName& other) const {
return //compare as apropriate.
}
However, I have to note two things:
First, you really need to go through the class design again -> there are wild inconsistencies in use of references, weird API and I am not even sure what exactly is minqueue is supposed to do, or rather why it does what it does.
Second, if you want to have queue that sorts itself, goes from minimal element and such, you should look up priority queue, or heap.
I'm implementing a Hash Table in C++ using chaining. The code builds with no errors and the table constucts fine using the insert method. However, when I call the remove method I receive the following error:
Unhandled exception at 0x00c53be9 in HashTable.exe: 0xC0000005: Access violation reading location 0x00000000.
Hash Entry Code:
#include <string>
#include <vector>
template <class T>
class HashEntry
{
private:
int key; //lookup key
T value; //hash data
HashEntry<T> *next;
public:
HashEntry(int key, T value);
HashEntry();
int& getKey();
T& getValue();
void setValue(T value);
HashEntry<T>* getNext();
void setNext(HashEntry *next);
bool operator == (HashEntry& rhs);
bool operator != (HashEntry& rhs);
HashEntry<T>& operator = (HashEntry& rhs);
};
template <class T>
HashEntry<T>::HashEntry(int key, T value)
{
this->key = key;
this->value = value;
this->next= nullptr;
}
template <class T>
HashEntry<T>::HashEntry()
{
this->key = 0;
this->next= nullptr;
}
template <class T>
int& HashEntry<T>::getKey()
{
return key;
}
template <class T>
T& HashEntry<T>::getValue()
{
return value;
}
template <class T>
void HashEntry<T>::setValue(T value)
{
this->value = value;
}
template <class T>
HashEntry<T>* HashEntry<T>::getNext()
{
return next;
}
template <class T>
void HashEntry<T>::setNext (HashEntry *next)
{
this->next = next;
}
template <class T>
bool HashEntry<T>::operator == (HashEntry& rhs)
{
return ((this->getKey() == rhs.getKey()) && (this->getValue() == rhs.getValue()));
}
template <class T>
bool HashEntry<T>::operator != (HashEntry& rhs)
{
return ((this->getKey() != rhs.getKey()) && (this->getValue() != rhs.getValue()));
}
template <class T>
HashEntry<T>& HashEntry<T>::operator = (HashEntry& rhs)
{
this->key = rhs.getKey();
this->value = rhs.getValue();
this->next = rhs.getNext();
return *this;
}
Hash Table code:
template <class T>
class HashTable
{
private:
std::vector<HashEntry<T>> table;
static const int DEFAULT_TABLE_SIZE = 128;
int TABLE_SIZE;
public:
HashTable();
void insert(int key, T value);
void remove(int key);
void get(int key);
~HashTable();
};
template <class T>
HashTable<T>::HashTable()
{
TABLE_SIZE = DEFAULT_TABLE_SIZE;
table.resize(TABLE_SIZE);
}
Remove Method Code:
template <class T>
void HashTable<T>::remove(int key)
{
int hashFunc = (key % TABLE_SIZE);
if (table[hashFunc] != HashEntry<T>())
{
HashEntry<T> prevEntry = HashEntry<T>();
HashEntry<T> entry = table[hashFunc];
while (entry.getNext() != nullptr && entry.getKey() != key)
{
prevEntry = entry;
entry = *entry.getNext();
}
if (entry.getKey() == key)
{
if (prevEntry == HashEntry<T>())
{
HashEntry<T> nextEntry = *entry.getNext(); //Where the exception is thrown
entry = HashEntry<T>();
table[hashFunc] = nextEntry;
}
else
{
HashEntry<T> *next = entry.getNext();
entry = HashEntry<T>();
prevEntry.setNext(next);
}
}
}
}
while (entry.getNext() != nullptr && entry.getKey() != key)
{
prevEntry = entry;
entry = *entry.getNext();
}
Few lines later, using entry generated above:
HashEntry<T> nextEntry = *entry.getNext(); //Where the exception is thrown
The while "makes" entry.getNext() a nullptr. And, later, you are trying to dereference it. And dereferencing nullptr... is a Bad Thing (tm).
Btw., why aren't you operating on pointers? I may be wrong, but looking at your code, I have a feeling that you want to modify original objects... and local objects looks like copies.
error C2664 : 'void std::vector<_Ty>::push_back(_Ty&&)': cannot convert parameter 1 from 'Node *' to 'Node&&'
please I need help...
I created node.h & heap.h
node.h :
#ifndef __NODE_H_
#define __NODE_H_
#include <string>
#include <iostream>
using namespace std;
template <class T>
class Node {
private:
Node<T>* m_brother;
int m_index;
T m_data;
public:
Node (T data);
~Node ();
int GetIndex () const;
int GetBrother () const;
void SetIndex (const int index);
void SetBrother (const Node<T>* brother);
void SetData (const T& data);
bool operator<(const Node<T>& other) const;
};
template <class T>
Node<T>::Node(T data) {
SetData(data);
}
template <class T>
int Node<T>::GetIndex () const {
return m_index;
}
template <class T>
int Node<T>::GetBrother () const {
return m_brother->GetIndex();
}
template <class T>
void Node<T>::SetData (const T& data) {
m_data = data;
}
template <class T>
void Node<T>::SetBrother(const Node<T>* brother) {
m_brother = brother;
}
template <class T>
void Node<T>::SetIndex(const int index) {
if (index > 0)
m_index = index;
else
cout <<"ERROR: Index Can't be negative number!"<<endl;
}
template <class T>
bool Node<T>:: operator<(const Node<T>& other)const
{
return *(this->GetData()) > *(other.GetData());
}
#endif
heap.h:
#ifndef __HEAP_H_
#define __HEAP_H_
#pragma once
#include <vector>
#include "Node.h"
using namespace std;
template<class T> class Heap {
public:
Heap();
virtual ~Heap();
Node<T> * CreateNode (T data);
bool IsEmpty() const;
Node<T>* RemoveNode(int indexNode);
Node<T>* ExtractMin ();
//void AddToHeap(Node<T>* newNode);
//void Add(int indexNode);
void Insert(Node<T>* newNode);
void DecreaseKey (Node<T>* newNode);
void Exchange (int indexNode1, int indexNode2);
void MinHeapify (int indexNode);
private:
vector<Node<T>> m_heap;
int num;
};
template<class T>
Heap<T>::Heap() {
}
template<class T>
Heap<T>::~Heap() {
}
template<class T>
Node<T>* Heap<T>::CreateNode(T data) {
Node<T*>* node(T);
return node;
}
template<class T>
bool Heap<T>::IsEmpty() const {
return (m_heap.size() == 0);
}
template<class T>
Node<T>* Heap<T>::RemoveNode (int indexNum) {
Node<T>* nodeToRemove=NULL;
if (indexNum > 0 && indexNum < m_heap.size()) {
nodeToRemove = m_heap[indexNum];
m_heap [indexNum] = m_heap [ m_heap.size()-1];
m_heap [m_heap.size()-1] = nodeToRemove;
m_heap.pop_back();
MinHeapify(nodeToRemove->GetIndex());
}
return nodeToRemove;
}
template<class T>
void Heap<T>::Insert(Node<T>* newNode) {
if (m_heap.size() == 0) {
m_heap.push_back(newNode);
}
else
DecreaseKey(newNode);
}
template<class T>
void Heap<T>::DecreaseKey(Node<T>* newNode) {
m_heap.push_back(newNode);
int index = m_heap.size();
while ((index > 0) && (m_heap[(index/2)-1] > m_heap[index-1])) {
Exchange(index,index/2);
index = index/2;
}
}
template<class T>
Node<T>* Heap<T>::ExtractMin () {
Node<T>* minNode;
minNode = m_heap[0];
m_heap[0] = m_heap[m_heap.size()-1];
m_heap.erase(m_heap[m_heap.size()-1]);
MinHeapify (0);
return minNode;
}
template<class T>
void Heap<T>::Exchange (int indexNode1, int indexNode2) {
Node<T>* tmp = m_heap[indexNode1-1];
m_heap[indexNode1-1] = m_heap [indexNode2-1];
m_heap[indexNode2-1] = tmp;
}
template<class T>
void Heap<T>::MinHeapify (int indexNode) {
int leftNode = 2*indexNode;
int rightNode = 2*indexNode+1;
int smallest = indexNode;
if ((leftNode < m_heap.size()-1) && (m_heap[leftNode-1]<m_heap[smallest-1]))
smallest = leftNode;
if ((rightNode < m_heap.size()-1) && (m_heap[rightNode-1]<m_heap[smallest-1]))
smallest = rightNode;
if (smallest != indexNode) {
Exchange (indexNode,smallest);
MinHeapify(smallest);
}
}
#endif;
In the main, I tried to check and it didn't compiled.
int main () {
Node<Vehicle*> a(car1);
Heap<Vehicle*> heap;
Node<Vehicle*>* p = &a;
heap.Insert(p);
return 0;
}
why?
Your Heap<T>::Insert function takes a Node<T*>*.
m_heap is defined as a vector<Node<T>>. You need to insert a Node<T*>, not a Node<T*>*. Heap<T>::Insert should take its parameter by const reference, not by pointer.
Your code uses a lot of pointers unnecessarily; it would be much simpler if you dealt with references and returned things by value rather than tangling with pointers all over the place.