前言
继上次用C++实现链表后,这次记录的是用C++实现栈和队列。经过上次的实现,现在对C++已经不那么陌生了,这次的实现几乎是一遍通过的。
代码
话不多说,上代码:
首先是CNode.h
#ifndef _NODE_H__
#define _NODE_H__
class CNode{
private:
int data;
CNode *nextNode;
public:
CNode();
void setData(int iData);
int getData() const;
void setNextNode(CNode *nextNode);
CNode* getNextNode() const;
};
#endif
以及DNode.h
#ifndef _DNODE_H__
#define _DNODE_H__
class DNode{
private:
int data;
DNode *preNode;
DNode *nextNode;
public:
DNode(){
this->preNode = NULL;
this->nextNode = NULL;
};
void setData(int iData){
data = iData;
};
int getData() const{
return data;
};
void setNextNode(DNode *nextNode){
this->nextNode = nextNode;
};
void setPreNode(DNode *preNode){
this->preNode = preNode;
};
DNode* getPreNode() const{
return preNode;
};
DNode* getNextNode() const{
return nextNode;
};
};
#endif
然后是Stack.h
#include "CNode.h"
class Stack {
private:
CNode *top;
public:
Stack();
~Stack();
void Push(int value);
void Pop();
int Peek();
bool IsEmpty();
};
接下来是Queue.h:
#pragma once
#include "CNode.h"
class Queue {
private:
CNode * front;
int data;
public:
Queue();
~Queue();
void Enqueue(int value);
void Dequeue();
int Peek();
bool IsEmpty();
};
接下来是Deque.h
#pragma once
#include "DNode.h"
#include "Queue.h"
class Deque :Queue{
private:
DNode *front;
DNode *back;
int data;
public:
Deque();
~Deque();
void Enqueue_Front(int value);
void Enqueue_Back(int value);
void Dequeue_Front();
void Dequeue_Back();
int Peek_Front();
int Peek_Back();
bool IsEmpty();
};
最后是main.cpp
#include <iostream>
#include "CNode.h"
#include "Deque.h"
#include "Queue.h"
#include "Stack.h"
using namespace std;
CNode::CNode(){
this->nextNode = NULL;
};
void CNode::setData(int iData){
this->data = iData;
};
int CNode::getData() const{
return data;
}
void CNode::setNextNode(CNode *nextNode){
this->nextNode = nextNode;
};
CNode* CNode::getNextNode() const{
return nextNode;
};
Stack::Stack(){
top = NULL;
};
Stack::~Stack(){
};
void Stack::Push(int value){
CNode *s = new CNode;
s->setData(value);
if (IsEmpty()) top = s;
else {
s->setNextNode(top);
top = s;//reset top node
}
return;
};
void Stack::Pop(){
if (IsEmpty()) ;
else top = top->getNextNode();
return;
};
int Stack::Peek(){
if (IsEmpty()) {
cout << "ERROR ";
return -1;
}
else return top->getData();
};
bool Stack::IsEmpty(){
if (top == NULL) return true;
else return false;
};
Queue::Queue(){
this->front = NULL;
data = 0;
};
Queue::~Queue(){
};
void Queue::Enqueue(int value){
data += 1;
CNode *s = new CNode;
CNode *p = new CNode;
s->setData(value);
p = front;
if (p == NULL) {
front = s;
return;
}
while (p->getNextNode() != NULL) p = p->getNextNode();
p->setNextNode(s);
return;
};
void Queue::Dequeue(){
data -= 1;
if (front == NULL)return;
front = front->getNextNode();
return;
};
int Queue::Peek(){
return front->getData();
};
bool Queue::IsEmpty(){
if (data == 0)return true;
//if(front==NULL) return true
else return false;
};
Deque::Deque(){
this->front = NULL;
this->back = NULL;
data = 0;
};
Deque::~Deque(){
};
void Deque::Enqueue_Front(int value){
data += 1;
DNode *s=new DNode;
s->setData(value);
if (front == NULL){
front = s;
back = front;
return;
}
s->setNextNode(front);
front->setPreNode(s);
front = s;//reset front node
return;
};
void Deque::Enqueue_Back(int value){
data += 1;
DNode *s=new DNode;
s->setData(value);
if (IsEmpty()){
front = s;
back = front;
return;
}
back->setNextNode(s);
s->setPreNode(back);
back = s;//reset back node
return;
};
void Deque::Dequeue_Front(){
data -= 1;
if (IsEmpty()) return;
else if (front == back){
front = NULL;
back = NULL;
return;
}
front = front->getNextNode();
return;
};
void Deque::Dequeue_Back(){
data -= 1;
if (IsEmpty()) return;
else if (front == back){
front = NULL;
back = NULL;
return;
}
back=back->getPreNode();
return;
};
int Deque::Peek_Front(){
if (IsEmpty()) {
cout << "ERROR ";
return -1;
}
return front->getData();
};
int Deque::Peek_Back(){
if (IsEmpty()) {
cout << "ERROR ";
return -1;
}
return back->getData();
};
bool Deque::IsEmpty(){
if (data==0) return true;
//if(front==NULL) return true
else return false;
};
int main(){
Stack s;
Queue q;
Deque d;
//the output should be 1 1 2 0 1 1
cout << "The output of stack test harness should be 1 1 2 0 1 1"<<endl;
cout << s.IsEmpty() << endl;//true, so 1
s.Push(1);
cout << s.Peek() << endl;//the top should be 1
s.Push(2);
cout << s.Peek() << endl;//the top should be 2
cout << s.IsEmpty() << endl;//false, so 0
s.Pop();
cout << s.Peek() << endl;//the top should be 1
s.Pop();
cout << s.IsEmpty() << endl;//true, so 1
//the output should be 1 1 1 0 2 1
cout << "The output of queue test harness should be 1 1 1 0 2 1" << endl;
cout << q.IsEmpty() << endl;//true, so 1
q.Enqueue(1);
cout << q.Peek() << endl;//the front should be 1
q.Enqueue(2);
cout << q.Peek() << endl;//the front should be 1
cout << q.IsEmpty() << endl;//false,so 0
q.Dequeue();
cout << q.Peek() << endl;//the front should be 2
q.Dequeue();
cout << q.IsEmpty() << endl;//true, so 1
//the output should be 1 3 2 0 1 1 1
cout << "The output of deque test harness should be 1 3 2 0 1 1 1" << endl;
cout << d.IsEmpty() << endl;//should be 1
d.Enqueue_Front(1);
d.Enqueue_Back(2);
d.Enqueue_Front(3);
cout << d.Peek_Front() << endl;//should be 3
cout << d.Peek_Back() << endl;//should be 2
d.Dequeue_Front();
d.Dequeue_Back();
cout << d.IsEmpty() << endl;//should be 0
cout << d.Peek_Front() << endl;//should be 1
cout << d.Peek_Back() << endl;//should be 1
d.Dequeue_Front();
cout << d.IsEmpty() << endl;//should be 1
}
注意点
过程当中没有遇到什么大问题,唯一查了资料的是在定义.h文件时使用到的#ifndef,#endif等字段。
#ifndef
#表明是预处理命令,ifndef意为if not defined sth.
它与ifdef都可用于条件编译,即:
#ifdef 标识符< A >
程序段1
#else
程序段2
#endif
意为若所指定的标识符A已经被#define命令定义过则编译程序段1,否则编译程序段2。
同理:
#ifndef 标识符< B >
程序段1
#else
程序段2
#endif
意为若所指定的标识符B未被#define命令定义过则编译程序段1,否则编译程序段2。
<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h
#ifndef _STDIO_H_
它的主要作用是用来防止头文件的重复包含和编译。
比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。如果把头文件的内容都放在#ifndef和#endif中,不管你的头文件会不会被多个文件引用,你都要加上这个,就可以避免冲突的问题。