Link to home
Start Free TrialLog in
Avatar of george08
george08

asked on

C++ Inheritance Polymorphism

I asked a similar question before (see https://www.experts-exchange.com/questions/23478995/Build-an-abstract-queueelement-class-and-inheritance-to-classe-queue-to-use-it-as-an-Object-within-a-queue-No-Idea.html) but i have to refine my question.

I do abstract.h , which is an abstract class of an queueElement. From those, i can inheritance/derive other classes like queueElementInt, queueElementFloat and so on.

I do also have a class Queue, in which I have to insert objects from the class queueElement as elements of my queue. On the queue i can perform certain operations like queue or dequeue, as seen in the code snippet

I did work with inheritance before (class QueueClass: public QueueElement) but it is a pretty silly inheritance, since QueueClass has nothing to do with QueueElement.

I also understand the using of ploymorphism, but it does not get into my mind if my solution, which i post in the codesnippets work. I appreciate all the great answers from all the fine people arround here.

Since this is a new angle of my question, i opened a new one to reward the good work of the people arround here. Please help me out of my misery
class QueueElement {
public:
virtual ~QueueElement(){} 
 double data;
 QueueElement *next;
 
	void setData(double d)
	{
    data=d;
  }
 
	double getData()
	 {
    return data;
  }
 
  
	QueueElement const *getNext() const
	{
    return next;
  }
};
/// no further inhertince to QueueElementint and so on done.
 
 
#include <iostream>
 
using namespace std;
 
#define SIZE 20
#include "abstract.h"
class QueueClass{
  private:
  int queue[SIZE];
  int head, tail;
  int num;
 
 public:
  QueueClass();
  void qu(QueueElement* newElement);  
  int dequ();
  int size();
  int isEmpty();
};
 
QueueClass::QueueClass()			
{
  head = tail = 0;
}
 
void QueueClass::qu(QueueElement* newElement)  
{												
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return;
  }
  tail++;
  if(tail==SIZE) tail = 0; 
  queue[tail] = num;
}
 
int QueueClass::dequ()
{
  if(head == tail) {
    cout << "Queue is empty\n";
    return 0;                    
  }
  head++;
  if(head==SIZE) head = 0;     
  return queue[head];
}
 
int QueueClass::size()
{
    int j=0;
  for (; j<tail; j++){
  }
  return j;
  }
 
 int QueueClass::isEmpty()
 {
    if(head == tail) {
    cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 
 }

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Infinity08
Infinity08
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of george08
george08

ASKER

To be exact, thats how it should work


I have to write an abstract Class QueueElement, which is the parent class for the objects, which i can put in my queue.


I already wrote a template, but it should be not a template this time, it should be done with inclusion polymorphism.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> And my Queue only stores Objects of QueueElement...??

Where ? You have an array of int to store the elements in the queue :

>>   int queue[SIZE];


Also, notice that your qu method doesn't make use of its parameter - it doesn't actually insert the element into the queue ...
The rest of the Queue class is also made for ints - did you copy this code from somewhere ? Do you understand it ?
Okey, here is my template queue i made myself with the help of other fine users arround here....

I think that this is a good point to start, is not it?

Within my template i do have my methode i.e.

void QueueClass<T>::qu(T num)             //init declarator before < token //expected ; befor < token
{  
      if(tail+1==head || (tail+1==SIZE && !head)) {
            cout << "Queue is full\n";
            return;
      }
      tail++;
      if(tail==SIZE) tail = 0;
      queue[tail] = num;
}

where i can replace T num by a pointer of the type QueueElement (Queueelement* newElement)

I do understand that i wrote a wrong virtual class, which i'm taking care of pretty soon.

But in the Meantime, please help me out on my other objective. Thanks!


///queuet.h
 
#ifndef QUEUET_H
#define QUEUET_H
 
#include <iostream>
using namespace std;
 
#define SIZE 20
 
template <typename T>
class QueueClass
{ 
 
  T queue[SIZE];
      T head, tail;
public:
 
 QueueClass(T, T);
 ~QueueClass(){};
  
 
  void qu(T num);
 
  T dequ();
  T size();
  T isEmpty();
};
 
#endif
 
////qeuet.cc
#include "QUEUET.H"
 
template <typename T>
QueueClass<T>::QueueClass (T a, T b) { 		//expected ; befor < token
	head = a; 
	tail = b; 				
 
}
 
template <typename T> 
 
void QueueClass<T>::qu(T num) 		//init declarator before < token //expected ; befor < token
{  
	if(tail+1==head || (tail+1==SIZE && !head)) {
		cout << "Queue is full\n";
		return;
	}
	tail++;
	if(tail==SIZE) tail = 0; 
	queue[tail] = num;
}
 
template <typename T> 
 
T QueueClass<T>::dequ()		//init declarator before < token //expected ; befor < token
{
	if(head == tail) {
		cout << "Queue is empty\n";
		return 0;                   
	}
	head++;
	if(head==SIZE) head = 0;       
	return queue[head];
}
 
template <typename T> 
T QueueClass<T>::size()
{ 							//init declarator before < token //expected ; befor < token
	T j=0;
	for (; j<tail; j++){
	}
	return j;
}
 
template <typename T> 
 
T QueueClass<T>::isEmpty()
{  				//init declarator before < token //expected ; befor < token
	if(head == tail) {
		cout << "Queue is empty\n";
		return 1;
	}
	else return 0;
}
 
/// main.cc
 
#include <iostream>
#include "queuet.cc"
using namespace std ;
int main()
{
	QueueClass<int> queue1 (1,1);  ////expected ; before int //QueueClass undeclared  //expect primary expression before int
 
	cout<<"If 1, Queue is Empty, else 0 aka Queue is not empty. Result: " <<queue1.isEmpty()<<endl;
	int i;
	for(i=1; i <=10; i++) {
		queue1.qu(i);        // queue1 undecleared, first use
	}
	cout<<"If 1, Queue is Empty, else 0 aka Queue is not empty. Result: " <<queue1.isEmpty()<<endl;
	cout<< queue1.size() <<" test" <<endl;
 
	for(i=1; i <=10; i++)
		cout << "Dequeue 1: " << queue1.dequ() << endl;
 
	return 0;
}

Open in new window

Here is my (hopefully) abstract class

#include <iostream>
using namespace std;
 
class QueueElement {
  private:
	QueueElement *next;
	double data;
  QueueElement(int d){
	data=d;
	next=0L;	
  }
   virtual ~QueueElement(){
   }
 
 
  virtual setData( d) =0;
 
  virtual QueueElement::getData() =0;
 
  virtual QueueElement::*getNext() =0;
 
 
};

Open in new window

Here we do have the abstract class and two other classes which derive from that

Is that correct?

We have got virtual functions, the destructor is virtual and in the derived classes, all functions where proper written. (Hopefully)

Thanks!

#include <iostream>
using namespace std;
 
class QueueElement {
  private:
	QueueElement *next;
	double data;
  QueueElement(int d){
	data=d;
	next=0L;	
  }
   virtual ~QueueElement(){
   }
 
 
  virtual setData( d) =0;
 
  virtual getData() =0;
 
  virtual *getNext() =0;
 
 
};
 
class QueueElementInt : public QueueElement
{
	public:
	QueueElementInt();
	~QueueElementInt();
	
	void setData(d){
	data=d;
	}
	
	int getData(){
	return data;
	}
	
	QueueElementInt *getNext(){
	return next;
	}
	};
 
	
	class QueueElementFloat : public QueueElement
{
	public:
	QueueElementInt();
	~QueueElementInt();
	
	void setData(d){
	data=d;
	}
	
	float getData(){
	return data;
	}
	
	QueueElementInt *getNext(){
	return next;
	}
	};

Open in new window

>> Okey, here is my template queue

I thought you said you shouldn't use templates ? Which is it ?


>> Here we do have the abstract class and two other classes which derive from that

It's abstract, but a few remarks :

1) What is the next member supposed to do ? You're not making a linked list are you ?

2) your setters and getters are missing a return type ...

3) your methods are all private ...

4) why did you choose a double data member for the ABC ? That doesn't make sense, does it ? The choice of data member should be left to the derived classes, no ?
I'm sure i can use my template class to change it so that i can use it as a raw modell for my new objective.

As I stated above, i need to put in objects of my QueueElement class in my Queue Class. And with a template, it should be easier to start on.

And please do me a favour, I'm not that experieciend in CPP, so do not give me a hard time. ;-) Finishing this work properly helps me really out of a serious situation....

To my abstract class:

I'm not totally sure about what is with my next member - a friend told me so. I changed it all back.
With that private and public: stupid mistake by me, sorry.


Please see below. Thanks.



#include <iostream>
using namespace std;
 
class QueueElement {
  private:
	double data;
  public:
  
  QueueElement(int d){
	data=d;
	next=0L;	
  }
   virtual ~QueueElement(){
   }
 
 
  virtual voidsetData( d) =0;
 
  virtual int getData() =0;
 
//  virtual *getNext() =0;
 
 
};
 
class QueueElementInt : public QueueElement
{
	public:
	QueueElementInt();
	~QueueElementInt();
	
	void setData(d){
	data=d;
	}
	
	int getData(){
	return data;
	}
	
 
	};
 
	
	class QueueElementFloat : public QueueElement
{
	public:
	QueueElementInt();
	~QueueElementInt();
	
	void setData(d){
	data=d;
	}
	
	float getData(){
	return data;
	}
	
	
	};

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I do understand the concept of ABC and interfaces as well as of virtual methods. But I'm NOT seeing the way of eleminating my int and double values in my ABC. I also do understand virtual methods, they are methods without a body, so that they can be written later in the derived class.

I also do understand the concept the concept of storing a pointer in the queue, this should be nothing else more than storing an int value to my queue. But I do not totally get it, I do know pointers but I'm not totally sure who to handle them properly. That is why I'm here, writing. I'm also willing to learn, but i did spent hours over hours over that and cannot make a step forward.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>>I'm sorry to say, but I don't think you do :) Not completely anyway.

Hey, I never said I'm perfect


>>Just don't put them in there ... put them in the derived classes. The ABC will NEVER be instantiated. It is simply an interface, nothing >>more. There's no data in it, nor is there any implementation in it.

That is a problem for me. You said above that i did not put a return type on me getter and setters... But which return type should i take? a virtual? All my google results does not give me a solution, they only say arbitrary....


>>That's not quite correct. I suggest you do some reading about them first. Here's a good start :

        http://www.parashift.com/c++-faq-lite/virtual-functions.html

I' reading, please see also above for my question about the propper return type


>>I'm not sure what you mean by that, but ints and pointers are quite different.

I do know that there is a difference, but for my queue, it should not matter if there are int parts in my queue or pointers...



>>I understand that, and I'm trying to teach ;)

I really appreciate your offer, I'm totally willing to listen.

Thanks


>> but i did spent hours over hours over that and cannot make a step forward.

You have to understand all the concepts involved first before starting to write code. If not, you end up wasting a lot of time as you noticed :)
>> Hey, I never said I'm perfect

It wasn't meant negatively. Just that the first step of learning something is to acknowledge that you need to learn it :)


>> You said above that i did not put a return type on me getter and setters... But which return type should i take? a virtual?

If the different derived classes will return different types, then that's not possible. In that case, you have to ask yourself if using an ABC is the right choice.

Virtual methods are good if you plan to store data of different types in the same queue.
Templated queues are good at handling queues of different element types without having to write the same code over and over.


Can you show me the exact assignment you got ? Because it seems there are some conflicting requirements there :)
The Assignement is not in English, that's the point. I'm not a native speaker also, as u might have seen ;-)

I was done to do an abstract class from which QueueElementWhatever1 and QueueElementWhateverII derive.
To surpass the system of having different return types, can't we eleminate the power of the virtual methods and put all the nesserary methods in the derived classes? That's not elegant, but it works.

Then i was asked to transform my template in that way, that i can put Queueelements to my queue.

That's another problem too. I know that i have to use polymorhism, but to my limited knowledge, i can only use polymorphis together with inheritance.

But i do not wanna use class QueueClass: public QueueElement

The Assignement is doable, that's for sure. And i got that advise about having to derived classes (whateverI and whateverII) and not using class QueueClass: public QueueElement

It should be done with polymorphism.

I hope you do understand my miserary and can help me out. Thanks.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thats it

Convert your class queue so that instead of templates now inheritance
(Inclusionspolymorphism). Write about an abstract
Class queue element, as the base class for the objects that would
in the queue will be.




See below my template, which works....


THANK YOU
#include "QUEUET.H"
 
template <typename T>
QueueClass<T>::QueueClass (T a, T b) { 		
	tail = b; 				
	head = a; 
 
}
 
template <typename T> 
 
void QueueClass<T>::qu(T num) 		
{  
	if(tail+1==head || (tail+1==SIZE && !head)) {
		cout << "Queue is full\n";
		return;
	}
	tail++;
	if(tail==SIZE) tail = 0; 
	queue[tail] = num;
}
 
template <typename T> 
 
T QueueClass<T>::dequ()		
{
	if(head == tail) {
		cout << "Queue is empty\n";
		return 0;                   
	}
	head++;
	if(head==SIZE) head = 0;       
	return queue[head];
}
 
template <typename T> 
T QueueClass<T>::size()
{ 							
	T j=0;
	for (; j<tail; j++){
	}
	return j;
}
 
template <typename T> 
 
T QueueClass<T>::isEmpty()
{  				
	if(head == tail) {
		cout << "Queue is empty\n";
		return 1;
	}
	else return 0;
}

Open in new window

>> now inheritance (Inclusionspolymorphism).

Inheritance is not the same as polymorphism. Please take a look at the tutorial and FAQ articles I posted earlier. I really suggest reading up on all these concepts before continuing. You seem to be rushing into this.

As I tried to explain earlier : you cannot just replace templates with polymorphism .. they're two completely different concepts used for different purposes.
google translate did a poor job on this

instead of template do inheritance, that's what i really is....
"instead templates do now inheritance "

thats the correct meaning. google translate was not perfect.

My problem with all tutorials you post... there is always an inheritance involved...

My problem is, that i cannot use inheritance von queueelement to queue...

that is what i do not get....
Here we go again...

I do have again my abstract class and two classes which derive from them. Because I do have two different classes derived from my base, i did chose double as data type.

Next step i do, is to write a queue.h (from my understanding i can also use my template?)

The third step would be writing a main.cc in which i include my queueelement headerfiles AND my queue.h file.

From thereon use constructors to construct objects of my queueelment and an object of my queue?


is that hopefully a correct thought? is that what ploymorphis is about?
#include <iostream>
using namespace std;
 
class QueueElement {
	private:
	double data;
	public:
  
	QueueElement(int d){
		data=d;
			
	}
   virtual ~QueueElement(){
   }
 
 
  virtual void set Data( d) =0;
 
  virtual double getData() =0;
 
 
 
};
 
class QueueElementFloat : public QueueElement
{
	public:
	QueueElementInt();
	~QueueElementInt();
	
	void setData(d){
	data=d;
	}
	
	double getData(){
	return data;
	}
	
 
	};
 
	
	class QueueElementDouble : public QueueElement
{
	public:
	QueueElementInt();
	~QueueElementInt();
	
	void setData(d){
	data=d;
	}
	
	double getData(){
	return data;
	}
	
	
	};

Open in new window

Forget what i said above...

I do have a base class and two derived classes.

So in my main, i construct one objects from my base class like this

QueueElementdouble *newElement;

which i can use in my queue.

To suceed, i do have to include my baseclass as well as my derived classes in my main file?

That should be polymorphism too?

Please do not laugh about me ;-)
>> My problem is, that i cannot use inheritance von queueelement to queue...

Who says you need to inherit Queue from QueueElement ? You have different types of QueueElements, don't you ? And all of them have one thing in common ... what ?


>> "instead templates do now inheritance "
>> (from my understanding i can also use my template?)
>> is that what ploymorphis is about?

??????? These three do not make a lot of sense together in the same post ...

Stop, rewind ... ;)

Did you find the time to read the tutorial I posted ? Did you understand all of it ?


I have to be honest, I still don't quite understand what the assignment is about - it just doesn't make sense to replace templates with inheritance (let alone polymorphism).

What was the original language the assignment was in ? Can you post that, and also the first assignment (the one for which you made the templated code) ?
>>Who says you need to inherit Queue from QueueElement ? You have different types of QueueElements, don't you ? And all of them have one thing in common ... what ?


Sorry, I'm too tired for guessing....

About the assignment:

Who said that assignement should make sense? ;-)
I just know that this assignement is doable and it can't be too problematic, but i cannot see the trick i have to perform on this.
The assignment ist german.

Tutorials
Yes, i do think that i do understood most of it, and i do know that i can use


QueueElementdouble *newElement;

to make a pointer to my base class. by doing so, i can use the pointer as a part of my queue.

>> I'm too tired for guessing....

I'm not asking you to guess ;) I'm asking you to try to understand this :) That's what this is about, isn't it.

If you're feeling tired, then maybe it's time to take a break, and start again later with a fresh head. And as I said a few times earlier already : understanding the concepts before writing any code is very important. You will only confuse yourself otherwise (as you've apparently been doing until now), and that works counterproductively.


>> The assignment ist german.

So ? can you post both of them ?
The Assignment
1. Schreiben Sie eine Klasse Queue (FIFO) ohne Verwendung von Template mit einem statischen Array
2. Formen Sie die Klasse in ein Template um
3. Wandeln Sie die Klasse Queue so um, dass statt einem Template nun Vererbung (Inklusionspolymorphismus) verwendet wird
Wandeln Sie Ihre Klasse Queue so um, daß statt Templates nun Vererbung.
Schreiben Sie dazu eine abstrakte Klasse QueueElement, die als Basisklasse fuer Objekte dient, die in der Queue abgelegt werden.

Both different QueueElements have their BaseClass in common. They also have in common that they are both capable of being part of the queue.

I don't see anywhere in this assignment that the queue elements need to contain data. So, for the third part, I would not put any data in at all. Just create a method that prints something to the screen or something similar. That should be more than sufficient to showcase polymorphism.


>> They also have in common that they are both capable of being part of the queue.

Exactly :) So, it's not the Queue class that inherits ...


I need to get some sleep now :)
thanks for your time and patience... good night
Here we go :-)

My abstract class an two classes which derive from these...
#include <iostream>
using namespace std;
 
class QueueElement {
	private:
	
	public:
  
	QueueElement(){
			
	}
   virtual ~QueueElement(){
   }
 
 
  virtual void print() =0;
 
 
};
 
class QueueElementFloat : public QueueElement
{
	public:
	QueueElementInt();
	~QueueElementInt();
	
	void print(){
	std::cout<<"I'm QueueElementFloat" <<std::endl;
	}
	
	};
 
	
	class QueueElementIny : public QueueElement
{
	public:
	QueueElementInt();
	~QueueElementInt();
	
	void print(){
	std::cout<<"I'm QueueElementInt" <<std::endl;
	}
	
	
	};

Open in new window

>> My abstract class an two classes which derive from these...

That looks good. You can do something with that. Now, modify the Queue class to hold these elements.
Here we go:
#include <iostream>
 
using namespace std;
 
#define SIZE 20
#include "abstract.h" //That should be my Base class
class QueueClass{
  private:
  int queue[SIZE];
  int head, tail;
  int num;
 
 public:
  QueueClass();
  void qu(QueueElement* newElement);  
  int dequ();
  int size();
  int isEmpty();
};
 
QueueClass::QueueClass()			
{
  head = tail = 0;
}
 
void QueueClass::qu(QueueElement* newElement)  
{												
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return;
  }
  tail++;
  if(tail==SIZE) tail = 0; 
  queue[tail] = num;
}
 
int QueueClass::dequ()
{
  if(head == tail) {
    cout << "Queue is empty\n";
    return 0;                    
  }
  head++;
  if(head==SIZE) head = 0;     
  return queue[head];
}
 
int QueueClass::size()
{
    int j=0;
  for (; j<tail; j++){
  }
  return j;
  }
 
 int QueueClass::isEmpty()
 {
    if(head == tail) {
    cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 
 }

Open in new window

That's the same as what you posted earlier. My comments are still valid. This is a queue that stores ints ... You have to make it store your queue elements.
Yeah I saw. Is there a possibitly of editing posts?

But now, my QueueClass should only hold QueueElements, not ints
#include "QUEUET.H"
 
 
QueueClass::QueueClass (QueueElement* a, QueueElement* b) { 		
	head = a; 
	tail = b; 				
 
}
 
 
 
void QueueClass::qu(QueueElement* num) 		
{  
	if(tail+1==head || (tail+1==SIZE && !head)) {
		cout << "Queue is full\n";
		return;
	}
	tail++;
	if(tail==SIZE) tail = 0; 
	queue[tail] = num;
}
 
 
 
QueueElement QueueClass::dequ()		
{
	if(head == tail) {
		cout << "Queue is empty\n";
		return 0;                   
	}
	head++;
	if(head==SIZE) head = 0;       
	return queue[head];
}
 
 
int QueueClass::size()
{ 							
	int j=0;
	for (; j<tail; j++){
	}
	return j;
}
 
 
 
boolean QueueClass::isEmpty()
{  				
	if(head == tail) {
		cout << "Queue is empty\n";
		return true;
	}
	else return false;
}

Open in new window

>> Is there a possibitly of editing posts?

No ;)


1) Why does your constructor take two pointers ? Shouldn't a queue have a default (empty) initialization ?


2) Wouldn't it be nice to have an isFull method ? And make sure to call it wherever appropriate (also the isEmpty method) ... you don't want to duplicate code ;)


3) Take a look at the return type for dequ.


4) What's the size method doing ? Do you need that loop ? Is it returning the correct result ?
I should start systematicly, I really tend to rush of to these things sometimes without thinking.

This is my Queue.h
#ifndef QUEUE_H
#define QUEUE_H
 
#include <iostream>
using namespace std;
 
#define SIZE 20
 
class QueueClass
{
 
  QueueElement queue[SIZE];
      QueueElement head, tail;
public:
 
 QueueClass();
 ~QueueClass(){};
 
 
  void qu(QueueElement* num);
 
  void dequ();
  int size();
  boolean isEmpty();
};
 
#endif

Open in new window

>> I should start systematicly

That's a very good idea ;)



>> #include <iostream>
>> using namespace std;

You are not making use of iostream in the header, so you shouldn't include it in the header.
Also, putting using namespace std; in a header file is almost always a bad idea, since you're dumping the whole std namespace into every file that (indirectly) includes the header file.



>>   QueueElement queue[SIZE];

In order to make use of the polymorphism, you'll have to store pointers rather than the elements themselves.


>>       QueueElement head, tail;

head and tail have to be pointers too, for obvious reasons. If you don't understand why, please ask.



>>   void dequ();

Don't you want to return something ?



>>   boolean isEmpty();

What's boolean ?
Don't you want an isFull too ?
>>That's a very good idea ;)
again, thanks for guiding me. i think this will be a very productiv day.


>>You are not making use of iostream in the header, so you shouldn't include it in the header.
>>Also, putting using namespace std; in a header file is almost always a bad idea, since you're dumping the whole std namespace into >>every file that (indirectly) includes the header file.

Someone told me that sometime, but i forgot.


>>In order to make use of the polymorphism, you'll have to store pointers rather than the elements themselves.
Point taken, see also codesnippet



>>   void dequ();

Why should I?

>>>>   boolean isEmpty();
>> What's boolean ?

Boolean should be a return typ. As i might remember, it could be done in java, which i learned better than cpp

>>Don't you want an isFull too ?
No intend in doing so... these methods i have should do just fine.
boolean is bool

How can i include my QueueElement to my Queue.h?
#ifndef QUEUE_H
#define QUEUE_H
 
 
 
#define SIZE 20
 
class QueueClass
{
 
  QueueElement* queue[SIZE];
      QueueElement* head, tail;
public:
 
 QueueClass();
 ~QueueClass(){};
 
 
  void qu(QueueElement* num);
 
  void dequ();
  int size();
  bool isEmpty();
};
 
#endif

Open in new window

This is my class Queue which should work.

But I do have still the question. How do I include my QueueElement?

#include <iostream>
 
 
#define SIZE 20
#include "abstract.h"
class QueueClass
{
 
  QueueElement* queue[SIZE];
      QueueElement* head, tail;
public:
 
 QueueClass();
 ~QueueClass(){};
 
 
  void qu(QueueElement* newElement);
 
  QueueElement* dequ();
  int size();
  bool isEmpty();
};
 
 
QueueClass::QueueClass()            
{
 
}
 
void QueueClass::qu(QueueElement* newElement)  
{                                                
  if(tail+1==head || (tail+1==SIZE && !head)) {
    std::cout << "Queue is full\n";
    return;
  }
  tail++;
  if(tail==SIZE) tail = 0;
  queue[tail] = newElement;
}
 
QueueElement* QueueClass::dequ()
{
  if(head == tail) {
    std::cout << "Queue is empty\n";
    return 0;                    
  }
  head++;
  if(head==SIZE) head = 0;     
  return queue[head];
}
 
int QueueClass::size()
{
    int j=0;
  for (; j<tail; j++){
  }
  return j;
  }
 
 bool QueueClass::isEmpty()
 {
    if(head == tail) {
    std::cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 
 }

Open in new window

>> >>   void dequ();
>> 
>> Why should I?

The point of de-queue-ing is to get the next element from the queue. If you don't return anything, then ... ;)


>> boolean is bool

Correct. There is no boolean type in C++ (unless you define it yourself). bool should be used instead.


>> >>Don't you want an isFull too ?
>> No intend in doing so... these methods i have should do just fine.

It will make the code a lot clearer, and your life a lot easier. I would add it :)


>> How can i include my QueueElement to my Queue.h?

Just include the header file that contains the class definitions for the QueueElement class.



>> This is my class Queue which should work.

Do you mean that that code you posted is the .cpp file ? Why did you re-write the QueueClass class ? You should have simply included the queueclass.h header file.




I said this earlier :

>> >>       QueueElement head, tail;
>> 
>> head and tail have to be pointers too, for obvious reasons. If you don't understand why, please ask.

But I just noticed that you are using head and tail as array indexes ... So, they need to be ints ... and properly initialized in the queue's constructor.



Also, take a look at this remark I made earlier :

>> 4) What's the size method doing ? Do you need that loop ? Is it returning the correct result ?

What is the size of the queue ? How can you easily calculate it ?
>>Do you mean that that code you posted is the .cpp file ? Why did you re-write the QueueClass class ? You should have simply included >>the queueclass.h header file.


Okay, I did make a step too much. Please show me where to start. I cannot see it in that moment. Also in regard to head and tail as int.


>> 4) What's the size method doing ? Do you need that loop ? Is it returning the correct result ?

To my knowledge, Size() just gives me back how many elements are in my array. I do run through my array until i find tail, then i know how many elements are in my queue.

>> >>   void dequ();
>>
>> Why should I?
>
>The point of de-queue-ing is to get the next element from the queue. If you don't return anything, then ... ;)

So I do have QueueElement* dequ(){}


> >>Don't you want an isFull too ?
>> No intend in doing so... these methods i have should do just fine.
>>
>>It will make the code a lot clearer, and your life a lot easier. I would add it :)

Where to begin?

bool isFull()
 {
   
 }

>> Okay, I did make a step too much. Please show me where to start.

What do you mean ? Can you show me all of the files you currently have ?



>> Also in regard to head and tail as int.

How are you using head and tail ? What type do they need to have in order to be able to use them that way ?



>> To my knowledge, Size() just gives me back how many elements are in my array.

Correct.

>> I do run through my array until i find tail, then i know how many elements are in my queue.

Let me repeat the other questions I asked :

>> Do you need that loop ? Is it returning the correct result ?




>> Where to begin?
>> 
>> bool isFull()
>>  {
>>   
>>  }

That's it - now just implement it ;)
>>The Assignment
>>1. Schreiben Sie eine Klasse Queue (FIFO) ohne Verwendung von Template mit einem statischen Array
>>2. Formen Sie die Klasse in ein Template um
>>3. Wandeln Sie die Klasse Queue so um, dass statt einem Template nun Vererbung (Inklusionspolymorphismus) verwendet wird
>>Wandeln Sie Ihre Klasse Queue so um, daß statt Templates nun Vererbung.
>>Schreiben Sie dazu eine abstrakte Klasse QueueElement, die als Basisklasse fuer Objekte dient, die in der Queue abgelegt werden.

The attached file incl. part 1, part 2 and part 3 which are different parts of my assignment.
>>int QueueClass::size()
>>{
>>    int j=0;
>>  for (; j<tail; j++){
>>  }
>>  return j;
>>  }

The loop runs from 0 up to the tail-1. I Think that is the mistake, because Size() gives me size-1

Correct?
>> The attached file incl. part 1, part 2 and part 3 which are different parts of my assignment.

I asked for the code, not the assignment ;)



>> The loop runs from 0 up to the tail-1. I Think that is the mistake, because Size() gives me size-1
>> 
>> Correct?

I'll ask the question once more : do you need that loop ?

Think about what head and tail are, and how the size of the queue is defined. Then think about how you can get that size ...
I just connect the code i wrote to my assignment, so that it can be easier to track down whats what....


Ok, to my loop problem. Since my loop does work, can't we concentrate on matters which are more important for me, please?
I gotta finish this thing up....
>> Since my loop does work

Actually it doesn't :)


>> can't we concentrate on matters which are more important for me, please?

You can concentrate on any of the issues I pointed out ... it's your choice. But in the end, you will have to fix all of them.

If you're unsure about what to do next, I suggest reading back a bit for all the issues I already pointed out.
My problem is, that I

a. do not see the error in the loop
b. don't see the point why i need isFull() Method, since I was told that empty() q() deq() and size() would be enough
c. you totally confused me whether to use head or tail with int....

So I asking to give me a hand and guide me. But with all that I have right now, i do not the the light i can walk towards....
>> a. do not see the error in the loop

I assumed you could read between the lines when I asked "do you need that loop ?". The answer is of course : no. There is no reason for the loop, since all it does is just count to a predefined value. You might as well just have returned that value. There's no need to waste processor cycles with a loop.

But then there's still the problem that the value returned is incorrect. The size of the queue is the distance between the head and the tail of the queue ... Let that sink in a bit, and then think about how you can calculate that.


>> b. don't see the point why i need isFull() Method, since I was told that empty() q() deq() and size() would be enough

The point is that you are already using code that determines whether the queue is full. If you put that in an isFull method, and call that method whenever you need to know whether the queue is full, your code will be a lot easier to read and maintain.

Similarly, you have an isEmpty function, but you don't use it. Instead, you duplicated the code to determine if the queue is empty, while you could have simply called the isEmpty method.


>> c. you totally confused me whether to use head or tail with int....

As I said : think about what head and tail are. Look at how you are using head and tail. Then determine which data type they need to be.
Take it one step at a time. You're only confusing yourself by trying to be too fast :)
first of all thanks.
But i do not care about optimizing the code, I'm trying to solve my problem and i do not care at the moment whether the code is inefficient. i just wanna write stable code, which just runs. optimizing comes later. So my concers are focused on getting this thing up running....

The problem in the difference between head and tail is that it is one too short for giving the real size, so it should be: (tail-head)+1


My head and my tails are parts of the queue, if its an int queue, its int, if its double queue its double if its QueueElement* Queue its QueueElement*
....

This whole thing is bugging me since more than 2 weeks now, and my final deadline is running out on monday.... :-(

>> But i do not care about optimizing the code

First of all, you should.

Second, what I said had nothing to do with optimizing code, but with making your own life (a lot) easier by writing proper code.

The point of assignments is to learn something. If you refuse to take my advice, and just continue on your own path, then I'm not sure what you're asking me to do here ...



>> so it should be: (tail-head)+1

What if head > tail ?



>> My head and my tails are parts of the queue, if its an int queue, its int, if its double queue its double if its QueueElement* Queue its QueueElement*

No. Take a closer look at how you use head and tail in your code. I'm starting to wonder whether you wrote the queue code yourself ... Did you ?
I wrote the code together with a friend, to be honest....
Here we go again.

int show me on which part of the array i am.
---
I do use the constructor with init the head and the tail by 0, with q() an element at the end of my array, at the tail.
---

---
bool isFull(){

  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return true;
  }
  else{
  return false
  }
----

>>What if head > tail ?

Since my queue is static with a specific SIZE

i can check

if(head<tail)
{
int = (tail-head)+1;
}
else{
int = (SIZE-head)+tail+1
}

so i did work on, but i do have a few more errors to kill

please see the code snippet

Line 36
//expected primary expression before  '*' token  //expected primary expression before  ';' token

Line 47
//invalid     conversion from  'int' to 'QueueElement'

Thanks
#include <iostream>
using namespace std;
 
#define SIZE 20
#include "queueel.h"
class QueueClass {
  int queue[SIZE];
      int head, tail;
public:
 
 QueueClass(int, int);
  ~QueueClass();
 
 
  void qu(QueueElement* newElement);
  QueueElement* dequ();
  int size();
  bool isEmpty();
  bool isFull();
};
QueueClass::~QueueClass () {}
QueueClass::QueueClass (int a, int b) {
  head = a;
  tail = b;
 
}
 
void QueueClass::qu(QueueElement* newElement)
{
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return;
  }
  tail++;
  if(tail==SIZE){ tail = 0; 
  queue[tail] = QueueElement*;//expected primary expression before  '*' token  //expected primary expression before  ';' token
  }
}
 
QueueElement* QueueClass::dequ()
{
  if(head == tail) {
    cout << "Queue is empty\n";
    return 0;                    
  }
  head++;
  if(head==SIZE) head = 0; //invalid     conversion from  'int' to 'QueueElement'
  return queue[head];
}
 
int QueueClass::size()
{
    int j=0;
  for (; j<tail; j++){
  }
  return j;
  }
 
 bool QueueClass::isEmpty()
 {
    if(head == tail) {
    cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 }
 bool QueueClass::isFull(){
 
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return true;
  }
  else{
  return false;
  }
  }

Open in new window

Line 36 gives out the following Error


invalid conversion from QueueElement* to int


In my Array, i wanna put a Pointer to QueueElement, but the programm expects an int... Why?


#include <iostream>
using namespace std;
 
#define SIZE 20
#include "queueel.h"
class QueueClass {
  int queue[SIZE];
      int head, tail;
public:
 
 QueueClass(int, int);
  ~QueueClass();
 
 
  void qu(QueueElement* newElement);
  int dequ();
  int size();
  bool isEmpty();
  bool isFull();
};
QueueClass::~QueueClass () {}
QueueClass::QueueClass (int a, int b) {
  head = a;
  tail = b;
 
}
 
void QueueClass::qu(QueueElement* newElement)
{
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return;
  }
  tail++;
  if(tail==SIZE){ tail = 0; 
  queue[tail] = newElement;//invalid conversion from QueueElement* to int
  }
}
 
int QueueClass::dequ()
{
  if(head == tail) {
    cout << "Queue is empty\n";
    return 0;                    
  }
  head++;
  if(head==SIZE) head = 0; //invalid     conversion from  'int' to 'QueueElement'
  return queue[head];
}
 
int QueueClass::size()
{
    int j=0;
  for (; j<tail; j++){
  }
  return j;
  }
 
 bool QueueClass::isEmpty()
 {
    if(head == tail) {
    cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 }
 bool QueueClass::isFull(){
 
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return true;
  }
  else{
  return false;
  }
  }

Open in new window

>> I do use the constructor with init the head and the tail by 0, with q() an element at the end of my array, at the tail.

Not in any code you posted. Can you point out where you do that ? Btw, are you sure that 0 is the correct value to initialize them to ?


>> bool isFull(){

ok. except that the cout should not really be there ...


>> if(head<tail)
>> {
>> int = (tail-head)+1;
>> }
>> else{
>> int = (SIZE-head)+tail+1
>> }

Does that give the correct value ? You need to be consistent with your choice of where head and tail point to ...



>>   queue[tail] = QueueElement*;//expected primary expression before  '*' token  //expected primary expression before  ';' token

I think the error is pretty clear, no ? What is that * doing there ?



>>   int queue[SIZE];

Why did you make it an array of int again ? I thought we already established that we need to store QueueElement*'s ?
>>Not in any code you posted. Can you point out where you do that ? Btw, are you sure that 0 is the correct value to initialize them to ?

I have to put my head and my tail somewhere... but i'm not sure whether to put them in the same place...

>> I think the error is pretty clear, no ? What is that * doing there ?

Corrected


>>   int queue[SIZE];

Corrected...



#include <iostream>
using namespace std;
 
#define SIZE 20
#include "queueel.h"
class QueueClass {
  QueueElement* queue[SIZE];
      int head, tail;
public:
 
 QueueClass(int, int);
  ~QueueClass();
 
 
  void qu(QueueElement* newElement);
  QueueElement* dequ();
  int size();
  bool isEmpty();
  bool isFull();
};
QueueClass::~QueueClass () {}
QueueClass::QueueClass (int a, int b) {
  head = a;
  tail = b;
 
}
 
void QueueClass::qu(QueueElement* newElement)
{
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return;
  }
  tail++;
  if(tail==SIZE){ tail = 0; 
  queue[tail] = newElement;//invalid conversion from QueueElement* to int
  }
}
 
QueueElement* QueueClass::dequ()
{
  if(head == tail) {
    cout << "Queue is empty\n";
    return 0;                    
  }
  head++;
  if(head==SIZE) head = 0; 
  return queue[head];
}
 
int QueueClass::size()
{
    int j=0;
  for (; j<tail; j++){
  }
  return j;
  }
 
 bool QueueClass::isEmpty()
 {
    if(head == tail) {
    cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 }
 bool QueueClass::isFull(){
 
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return true;
  }
  else{
  return false;
  }
  }

Open in new window

>>  QueueClass(int, int);

What's the point of this constructor ? You should only have a default constructor that initializes head and tail to the correct values (be consistent).
Okay, then should the compiler write the constructor himself. But how to init head and tail correctly?


#include <iostream>
using namespace std;
 
#define SIZE 20
#include "queueel.h"
class QueueClass {
  QueueElement* queue[SIZE];
      int head, tail;
public:
 
// QueueClass(int, int); 
  ~QueueClass();
 
 
  void qu(QueueElement* newElement);
  QueueElement* dequ();
  int size();
  bool isEmpty();
  bool isFull();
};
QueueClass::~QueueClass () {}
//QueueClass::QueueClass (int  a, int b) { 
//  head = a;
//  tail = b;
//
//}
 
void QueueClass::qu(QueueElement* newElement)
{
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return;
  }
  tail++;
  if(tail==SIZE){ tail = 0; 
  queue[tail] = newElement;//invalid conversion from QueueElement* to int
  }
}
 
QueueElement* QueueClass::dequ()
{
  if(head == tail) {
    cout << "Queue is empty\n";
    return 0;                    
  }
  head++;
  if(head==SIZE) head = 0; 
  return queue[head];
}
 
int QueueClass::size()
{
    int j=0;
  for (; j<tail; j++){
  }
  return j;
  }
 
 bool QueueClass::isEmpty()
 {
    if(head == tail) {
    cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 }
 bool QueueClass::isFull(){
 
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return true;
  }
  else{
  return false;
  }
  }

Open in new window

>> Okay, then should the compiler write the constructor himself.

No, you should write it.


>> But how to init head and tail correctly?

You said you wrote the queue class. If so, you know how you defined head and tail. With that knowledge, you know how to correctly initialize them. Which element does head refer to, and which does tail refer to ?
To my knowledge, the head and the tail refer at the beginning to the first element of my static array....

That's why i thought i should init them with 0....

If that is not correct, please give me additional hints....
>> the head and the tail refer at the beginning to the first element of my static array....

What do head and tail refer to when some data is in the queue ?
to the position in the queue, where data is put in
>> to the position in the queue, where data is put in

?? What do head and tail refer to in the normal case ? Theree are two parts in the question : one for head, and one for tail ;)
The head refers to the first element i put into the queue and the tails refers to the last element i put in the queue. since we have an order we put the elements in, there are different positions
>> and the tails refers to the last element i put in the queue.

Then how come that when the queue is empty, you say that both head and tail refer to position 0 ? That would mean there is one element in the queue (that is both the first and the last).
i got your point. so i do init the constructor with an empty body

QueueClass(){}

That should do?
>> so i do init the constructor with an empty body

No. As I've said a few times already : you need to initialize head and tail to proper values. Which values for head and tail would signify an empty queue ?
Null?
null ? ints cannot have a null value.

Take a look at the isEmpty method ... which values of head and tail would make it empty ?
if they both have the same values...
>> if they both have the same values...

And is that consistent with what you said earlier ?

>> The head refers to the first element i put into the queue and the tails refers to the last element i put in the queue.
no ;-)



because my first queue should be empty, both have the same values, so a constructor with one parameter should be enough...
But i do not get the value i should put in my paramter

QueueClass(int a){

head, tail = a;
}
>> no ;-)

So, how will you fix it ? How will you define head and tail ?


>> so a constructor with one parameter should be enough...

Why do you keep insisting on passing a parameter to the constructor ? There's no reason for that as I've said a few times already.
can we move that please to tommorow? i pretty tired...

but thanks a lot for your contious help :-)
No problem. Have a good night :)
thanks!!!!
>>So, how will you fix it ? How will you define head and tail ?

int head, tail;


If I do have a queue as an int array, we can assume that the array starts with 0 up to something.
If we put head and tail both to 0, there is one element in my queue
If i put head and tail both to -1, there is non element in my queue, therefore the queue is empty
If i q(), tail will go up to one, therefore i do have one element in my queue
if i q() again, tail go up to two, i do have two elements in my queue.



And if the constructor does not have a parameter list, i can only use an init list to init head an tail


Does this work out?
#include <iostream>
using namespace std;
 
#define SIZE 20
#include "queueel.h"
class QueueClass {
  QueueElement* queue[SIZE];
      int head, tail;
public:
 
QueueClass(); 
  ~QueueClass();
 
 
  void qu(QueueElement* newElement);
  QueueElement* dequ();
  int size();
  bool isEmpty();
  bool isFull();
};
QueueClass::QueueClass():  head(-1) , tail(-1){}
QueueClass::~QueueClass () {}
 
 
void QueueClass::qu(QueueElement* newElement)
{
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return;
  }
  tail++;
  if(tail==SIZE){ tail = 0; 
  queue[tail] = newElement;//invalid conversion from QueueElement* to int
  }
}
 
QueueElement* QueueClass::dequ()
{
  if(head == tail) {
    cout << "Queue is empty\n";
    return 0;                    
  }
  head++;
  if(head==SIZE) head = 0; 
  return queue[head];
}
 
int QueueClass::size()
{
    int j=0;
  for (; j<tail; j++){
  }
  return j;
  }
 
 bool QueueClass::isEmpty()
 {
    if(head == tail) {
    cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 }
 bool QueueClass::isFull(){
 
  if(tail+1==head || (tail+1==SIZE && !head)) {
    cout << "Queue is full\n";
    return true;
  }
  else{
  return false;
  }
  }

Open in new window

>> If i put head and tail both to -1, there is non element in my queue, therefore the queue is empty

Will that be compatible with your qu and dequ methods ? Ie. Try setting head and tail to -1, and then call the qu method. See what head and tail are set to now. Is that correct ?


>> And if the constructor does not have a parameter list, i can only use an init list to init head an tail

You can use the body of the constructor too, but init list is fine.
No, that's not correct.
Is my error probably that i did put head at the end and tail at the beginning?

Because you always talk about consistency?

>> Because you always talk about consistency?

You need to choose where head is and where tail is, and then use that consistently in all code in the stack. Right now, each method uses a different interpretation of head and tail - that doesn't work out so well.

So, start by choosing how head and tail will be defined, and then modify all code according to it.
thanks. can we please go that through together. i know what i'm looking for, but i cannot connect all the dots correctly...

I do have a static array of lets say 20 elements.

Head is at the Ende, Tail in the front.

Is that the correct start?
>> Head is at the Ende, Tail in the front.

Why ?
i can also switch it round, but in the end, it should not matter, should it?
The head is always at the front - why else would you call it a head ?

Now, what will head refer to, and what will tail refer to ?
The Head refers to the beginning of the array, the tail is refering to the end of the array.


Head[][][][][][][][][][][]Tail

But as we discussed earlier yesterday, Head cannot be init with 0, because this means that there is an element in my queue



OK, i hopefully did change the heads and tail arround, can you please check that
#include <iostream>
using namespace std;
 
#define SIZE 20
#include "queueel.h"
class QueueClass {
  QueueElement* queue[SIZE];
      int head, tail;
public:
 
QueueClass(); 
  ~QueueClass();
 
 
  void qu(QueueElement* newElement);
  QueueElement* dequ();
  int size();
  bool isEmpty();
  bool isFull();
};
QueueClass::QueueClass():  head(-1) , tail(-1){} // -1 is not correct init list is fine
QueueClass::~QueueClass () {}
 
 
void QueueClass::qu(QueueElement* newElement) //ok
{
  if(head+1==tail || (head+1==SIZE && !tail)) { //ok //head is tail before and tail is head before
    cout << "Queue is full\n";
    return;
  }
  head++;
  if(head==SIZE){ head = 0; 
  queue[head] = newElement;//invalid conversion from QueueElement* to int
  }
}
 
QueueElement* QueueClass::dequ()
{
  if(tail == head) {
    cout << "Queue is empty\n";
    return 0;                    
  }
  tail++;
  if(tail==SIZE) tail = 0; 
  return queue[head];
}
 
int QueueClass::size()
{
    int j=0;
  for (; j<tail; j++){
  }
  return j;
  }
 
 bool QueueClass::isEmpty()
 {
    if(head == tail) {
    cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 }
 //bool QueueClass::isFull(){
//
//  if(tail+1==head || (tail+1==SIZE && !head)) {
//    cout << "Queue is full\n";
//    return true;
//  }
//  else{
//  return false;
//  }
  }

Open in new window

>> The Head refers to the beginning of the array, the tail is refering to the end of the array.

I mean : which element in the queue does head refer to ? And which does tail refer to ?
If the Queue is empty, both head and tail refer to the same element, because that is the condition which is implemented in empty()


To be honest.

I do feel more and more unsure whether I'm doing the right thing so i would be pleased if you can give me helping hand bei actually correction a code snippet with me, that i can use this confidence that this is correct to move on...

At the moment, i do see all the parts of my code wrong and false.... :-(
>> because that is the condition which is implemented in empty()

That's a false premise. As I said earlier, FIRST decide how head and tail are defined, THEN implement it. Do not look at the current implementation of isEmpty. Just think about how you'll define head and tail.

If you want me to help you, then please follow my indications. This must be the tenth time that I'm trying to get you to define head and tail without going off on some wild goose chase.
>> If you want me to help you, then please follow my indications. This must be the tenth time that I'm trying to get you to define head >>and tail without going off on some wild goose chase.


I'm very thankfull that you try to help me, although you might be bored by telling some stupid jerk the millionth time to define the head and the tail. I do well understand that, but I cannot see or think of the solution to the problem you gave to me, and the result is a wild goose chase with to direction or movement at all...

So I beg you to give me some more hint... so that I can work on it together with you as a guide. Otherwise I would be lost...

You said this earlier :

>> The head refers to the first element i put into the queue and the tails refers to the last element i put in the queue.

In order to advance, let's take this as the definition of head and tail. Please do NOT deviate from this definition from now on. This is the definition, and from now on we'll work with that.

Next step :

1) using this definition of head and tail, what does a full queue look like - ie. what relation will there be between head and tail ?

2) same question for an empty queue
Thanks.

We can also assume that the queue is an array of 20 element, the first element is on the position 0, the last ist 19. That make things less abstract for me

if the queue is FULL, the head is on the element 0, the tail is on the element 19
if the queue is EMPTY, there are no elements int the queue, therefor no head an tail.

Correct?
>> if the queue is FULL, the head is on the element 0, the tail is on the element 19

The head is not necessarily at 0.


>> if the queue is EMPTY, there are no elements int the queue, therefor no head an tail.

head and tail HAVE to have a value. Which one ? Make sure that it doesn't clash with the definition of head and tail.
I'm gonna be offline for a while now.
can we talk tommorow or today again?
>>head and tail HAVE to have a value. Which one ? Make sure that it doesn't clash with the definition of head and tail.

We only do have values from 0 to 19, right?
So, after some more work...

I changed my methods, i think did a lot of things wrong, hopefully its better now

Head and Tail are hopefully back in order, the compiler linked and did not find errors.


But i still do not know how to init them properly....
#include <iostream>
using namespace std;
 
#define SIZE 20
#include "queueel.h"
class QueueClass {
  QueueElement* queue[SIZE];
      int head, tail;
public:
 
QueueClass(); 
  ~QueueClass();
 
 
  void qu(QueueElement* newElement);
  QueueElement* dequ();
  int size();
  bool isEmpty();
  
};
QueueClass::QueueClass():  head(-1) , tail(-1){} // -1 is not correct init list is fine
QueueClass::~QueueClass () {}
 
 
void QueueClass::qu(QueueElement* newElement) //ok
{
	if(isEmpty()){
	queue[head]=queue[tail]=newElement;
	}
	else{
	tail++;
	queue[tail] = newElement;
	}
}
 
QueueElement* QueueClass::dequ()
{
  if (isEmpty()) {return NULL;}
  else
  {
  tail--;
  return queue[tail]; //or head?
  }
}
 
int QueueClass::size()
{
	if(isEmpty()) {return 0;}
	else
	
	return tail;
}
 
 bool QueueClass::isEmpty()
 {
    if(head == tail) {
    cout << "Queue is empty\n";
    return 1;
    }
    else return 0;
 }

Open in new window

>> the compiler linked and did not find errors.

That doesn't mean that the program logic is ok.

In fact, it still isn't. You again have tried to go too fast.

Please, go back to this post, and answer it the way I asked : http:#21837131

You HAVE to get the answers to these questions correct. If you don't, there's no sense in continuing, because you will only waste time writing code that doesn't make sense.
Ok, thanks for your contiuning help,

>>>>head and tail HAVE to have a value. Which one ? Make sure that it doesn't clash with the definition of head and tail.

>>We only do have values from 0 to 19, right?


?

>>We only do have values from 0 to 19, right?

I'm not asking about specific values - just conceptually. What's the relation between the head and tail values in both the empty and full queue cases ?
from my understanding, the queue is nothing else but a waiting line.
The Head is always in front of the tail
my browser just crashed..

If I q the first element, it is the head and at the same time the tail
If I q the second element, this one is behind the head and so on.
If I deq the head, the second element becomes my head.....
>> If I q the first element, it is the head and at the same time the tail

Good.


>> If I q the second element, this one is behind the head and so on.

Ok.


>> If I deq the head, the second element becomes my head.....

Ok.

Those are the general cases. Now, the specific cases I asked about : a full and empty queue.

What happens if you queue 20 elements in your queue. What will head and tail be ?
What happens if you pop all elements from the queue. What will head and tail be ?
If I queue 20 elements in my queue, the head is on position 0 and the tail is on position 19

If I do pop all elements on the queue, there is no head and no tail, because the first element which i queue defines the head on the position it pushs in.

But I'm not shure if the head must be on position 0 or 1 or whereever
>> If I queue 20 elements in my queue, the head is on position 0 and the tail is on position 19

As I said earlier : the head is not necessarily at 0.

But anyway, in your example : what's the relation between 0 and 19 ... How would you know if a queue is full based on the head and tail values ?


>> If I do pop all elements on the queue, there is no head and no tail,

There is always a head and a tail. Just do the exercise on paper : push a few elements on the queue, and then pop all of them. Take note of the head and tail values for each step.
>>But anyway, in your example : what's the relation between 0 and 19 ... How would you know if a queue is full based on the head and tail values ?


Tail - Head must be 19 as result


>>There is always a head and a tail. Just do the exercise on paper : push a few elements on the queue, and then pop all of them. Take >>note of the head and tail values for each step.

The Head is defined as being front of the tail.

If i do push one element on position 0, my head and my tail is 0.
If i do have none elements in my queue, i know that the head is in front of the tail



>> Tail - Head must be 19 as result

Or, easier ?

What if head is not 0 ?


>> The Head is defined as being front of the tail.

What do you mean by "in front" ? Can you give an example ?
>>Or, easier ?
>>What if head is not 0 ?

OK, lets refine. The maximum result can be 19.



>>What do you mean by "in front" ? Can you give an example ?

[Elem1] Head on pos. 0, tail is on pos 0
[Elem2] Head on pos 0, tail is on pos 1
[Elem3]Head on pos 0, tail is on pos2
...

Since we do have a fifo structure, there the first element (head) which is put in is also the first element to pop out, the head must always be in front of tail


>> OK, lets refine. The maximum result can be 19.

What does that change ? Suppose head is 5, what will tail be if the queue is full ?


>> [Elem1] Head on pos. 0, tail is on pos 0
>> [Elem2] Head on pos 0, tail is on pos 1
>> [Elem3]Head on pos 0, tail is on pos2

Now, pop these three elements off the queue, and list the head and tail values.
>>What does that change ? Suppose head is 5, what will tail be if the queue is full ?
 The Tail can be 4


>>Now, pop these three elements off the queue, and list the head and tail values.

[Empty] Head is here, but since there is nothing in, we cannot tell about the position.... same to the tail
[Empty]
[Empty]
>>  The Tail can be 4

The tail WILL be 4.

Now, what is the relation between tail and head if the queue is full ?


>> >>Now, pop these three elements off the queue, and list the head and tail values.

Pop the 3 elements out of the queue, one by one. And show one line for each pop.
The difference is 0 when full, if empty, its 19



>> [Elem1] Head on pos. 0, tail is on pos 0
>> [Elem2] Head on pos 0, tail is on pos 1
>> [Elem3]Head on pos 0, tail is on pos2

pop Elem3

 [Elem1] Head on pos. 0, tail is on pos 0
 [Elem2] Head on pos 0, tail is on pos 1

pop Elem2

[Elem1] Head on pos. 0, tail is on pos 0

pop Elem2

Head on pos 19, Tail on 0 ??????? can that be
>> The difference is 0 when full,

How do you get that ? If head is at 5 and tail at 4, then the queue is full ... Is the difference 0 ?


>> pop Elem3

in a queue you have to pop the first element first ... ie. pop elem1 first. It's a FIFO structure, remember (first-in-first-out)


>>How do you get that ? If head is at 5 and tail at 4, then the queue is full ... Is the difference 0 ?

The difference is 1, if head-tail or -1 if tail-head


>>in a queue you have to pop the first element first ... ie. pop elem1 first. It's a FIFO structure, remember (first-in-first-out)

Thanks!



pop Elem1

 [Elem2] Head on pos. 1, tail is on pos 2
 [Elem3] Head on pos 1, tail is on pos 2

pop Elem2

[Elem3] Head on pos. 2, tail is on pos 2

pop Elem3
[Empty] Head's last pos was 2, tail's last pos was 2, so the new pos of the head if new elem is added is 2 again.
>> The difference is 1, if head-tail or -1 if tail-head

ok. Don't forget the special case where head is 0.



>> pop Elem1

After pushing the third element, the queue was in this state, remember :

>> Head on pos 0, tail is on pos2

Now, start popping, and adjusting head and tail accordingly.
My first try for isEmpty()


bool isEmpty()
{
  if (head>tail){
  head-tail ==1;
 std::cout<<"true" <<std::endl;
 return 1;
 
 }
 else if(head<tail){
 tail-head==-1;
 std::cout<<"true" <<std::endl;
 return 1;
 }
 else if(head==0, tail==0){
 std::cout<<"true" <<std::endl;
 return 1;
 }
 else{
 std::cout<<"false" <<std::endl;
 return 0;
 }
}

Open in new window

>>After pushing the third element, the queue was in this state, remember :

>>>> Head on pos 0, tail is on pos2

>>Now, start popping, and adjusting head and tail accordingly.


a head 0, tail 0
b head 0 tail 1
c head 0 tail 2

pop a

b head 1, tail 1
c head 1, tail 2

pop b

c head 2, tail 2

browser again :-(

pop c

head was on 2, tail was on 2
>> My first try for isEmpty()

Don't get ahead of yourself. First answer both questions.


>> a head 0, tail 0
>> b head 0 tail 1
>> c head 0 tail 2

Euhm ... what does this notation mean ? At each given moment, the queue has only one head and tail value - it does NOT have a head and tail value for each element.

So, I'll get you started :

after pushing the first element : head = 0, tail = 0
after pushing the second element : head = 0, tail = 1
after pushing the third element : head = 0, tail = 2

after popping the first element : head = ?, tail = ?
after popping the second element : head = ?, tail = ?
after popping the third element : head = ?, tail = ?

You fill in the question marks.
thanks!

after pushing the first element : head = 0, tail = 0
after pushing the second element : head = 0, tail = 1
after pushing the third element : head = 0, tail = 2

after popping the first element : head = 1, tail = 2
after popping the second element : head = 2, tail = 2
after popping the third element : head = ?, tail = ? <<< if can't be 2,2 otherwise we have another element.

So we have to reset the queue to have no element on it. Head can be 0, and Tail can be Size-1

If we q , we increment the tail by 1 and do have again one element in the queue with head 0, tail 0
>> after popping the third element : head = ?, tail = ? <<< if can't be 2,2 otherwise we have another element.

What would be the logical next step after these two ?

>> after popping the first element : head = 1, tail = 2
>> after popping the second element : head = 2, tail = 2
head =3, tail =2

?
>> head =3, tail =2

Correct. Now what's the relation between head and tail for a full list ?
if we do have a full list and

head =0, tail =19 we do have the size as a result of tail-head.

but i do not fully undestand in which context you mean 'relation" obiously i do misunderstand this word in its context
Do it for this specific case :

>> head =3, tail =2

Just like you did it for a full list earlier :

>> >>How do you get that ? If head is at 5 and tail at 4, then the queue is full ... Is the difference 0 ?
>> 
>> The difference is 1, if head-tail or -1 if tail-head
head 3  - tail 2 = 1

That means that the queue is empty.

if we do have head 2, tail 3, the queue is not empty.


so i can be done that:

if((head>tail)&&(head-tail==1)){

return 1;
}
else{
return 0;
}
>> head 3  - tail 2 = 1
>> 
>> That means that the queue is empty.

Does it ? Take a look at your earlier observation about a full queue :

>> The difference is 1, if head-tail

See any similarities ?
i'm wrong, again. thats what i see which helps me to explore how much frustration i can take ;-)


To look at the end of the queue would certainly help me to see whether the queue is empty or not....
That is - i my limited point of view- the only chance to see if it is empty....


right?

We do have out queue with 20 elements, we popped 17 Elements so far

>> after popping the 18th element : head = 19, tail = 19
>> after popping the 19th element : head 0, tail = 19


Correct?
Can you answer my question ?

>> >> head 3  - tail 2 = 1
>> >>
>> >> That means that the queue is empty.
>> 
>> Does it ? Take a look at your earlier observation about a full queue :
>> 
>> >> The difference is 1, if head-tail
>> 
>> See any similarities ?
1 means the the queue is full to answer your question.
>> >> See any similarities ?
The similarity i do see is that if the head is before the tail, we do have a full queue
Do you see a similarity between :

>> >> head 3  - tail 2 = 1
>> >>
>> >> That means that the queue is empty.

and :

>> >> The difference is 1, if head-tail

(the latter for a full queue).
I maybe not catching your point here, maybe i do not see it here or i'm too stupid...


in one we dequeue until the head is behind the tail......

in another case, the head is behind the tail because we filled up our queue and circulated until we reached the postion in front of head....


That is all i can see here, the rest is too confusing for me.....
I'll spell it out for you :

if head - tail = 1 then the queue is empty
if head - tail = 1 then the queue is full

See the similarity now ?
so that means that full and empty is the same?

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thanks.....

so i do have to run through my queue with a for loop and look at each array, whether it contains QueueElement* or not

Something like this

int counter =0;
      for(int i =o, i<size, i++){
      if queue[QueueElement*]{
      counter++
      }
      }

If counter==0 && head-tail==1 i can tell that the queue is empty... otherwise not

then i check if counter == size, then queue is full


That's why you insisted so hard on the full()...

thanks for all that guiding... i really appreciate...
That still leaves me with one questions... how to init the head and the tail...

Is tail=19 and head=0 ok?

If I queue an element, i do increment tail by one and put my new element to queue[tail]

If I dequeue the first element, i increment the head by one and return the head?

Does this works out?

Please answer....
Could someone please help me?
>> so i do have to run through my queue with a for loop and look at each array, whether it contains QueueElement* or not

Euh, no. Just keep a size member. If it's 0, then the queue is empty. If it has the maximum value, then the queue is full. You don't need to iterate.