温故而知新 -> 数据结构 ->利用 队列 实现 栈 -> 程序实现2_利用类
本篇博客是基于 温故而知新 -> 数据结构 -> 线性表 ->队列 && 栈 中利用 队列 实现 栈 的理论知识进行程序实现!
其中结合了 温故而知新->数据结构->队列->程序实现2_利用类 中的代码,实现了 栈 的 增(入栈)删(出栈)查(栈顶元素)改(没写(~ ̄▽ ̄)~),判空,打印等操作!并附带了上述 队列 与 利用其所实现的栈 的对比实例以及对应的运行结果!
注意1:在利用队列实现栈的时候,分别采用了 一个队列 与 两个队列 的实现方式进行实现,该内容在下述程序中会有对比说明!
注意2:其中代码有很大冗余,且未考虑性能最优,读者有兴趣可进一步精简!
具体内容如下
(1)QStack.h
#pragma once
#include<iostream>
using namespace std;
#include<assert.h>
typedef int QDataType;
typedef struct QNode
{
QDataType _val;
struct QNode *_next;
};
QNode *createQNode(QDataType val)
{
QNode *node = (QNode*)malloc(sizeof(QNode));
node->_val = val;
node->_next = nullptr;
return node;
}
class Queue
{
public:
Queue() :_front(nullptr)
, _rear(nullptr)
, _size(0)
{}
~Queue()
{
if (_front != NULL)//不是空队列
{
QNode *next = _front;
while (_front != NULL)
{
_front = _front->_next;
free(next);
next = _front;
}
_front = _rear = NULL;
}
}
// 队尾入队列
void QueuePush(QDataType data);
// 队头出队列
void QueuePop();
// 打印队列
void QueuePrint();
// 获取队列头部元素
QDataType QueueFront();
// 获取队列队尾元素
QDataType QueueRear();
// 获取队列中有效元素个数
int QueueSize();
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty();
QNode *_front;//队头 -- 取出数据 --改变他的权限是为了后面的操作
private:
QNode *_rear; //队尾 -- 插入数据
int _size; //队列中元素个数
};
class Stack :public Queue
{
public:
Stack()
{
q = new Queue();
q2 = new Queue();
}
~Stack()
{
delete(q);
delete(q2);
}
// 插入 - 入栈 (相当于是尾插)
void stackPush(QDataType val);
// 删除 - 出栈 (相当于是尾删)
void stackPop();
// 元素个数
int stackSize();
// 判空
bool stackEmpty();
// 获取栈顶元素 -- 直接返回数据即可
QDataType stackTop();
// 栈内元素打印
void stackPrint();
private:
Queue *q; // 利用一个队列实现栈
Queue *q2;// 利用2个队列实现栈,此时 q 也会被使用
};
(2)main.cpp
#include"QStack.h"
/* 先结合单链表进行实现队列的定义 */
// 队尾入队列
void Queue::QueuePush(QDataType data)
{
QNode *node = createQNode(data);
if (_front == NULL) //此处主要是判断是否是空队列
_front = _rear = node;
else
{
_rear->_next = node;
_rear = node;
}
_size++;
}
// 队头出队列
void Queue::QueuePop()
{
assert(_front != NULL);
QNode *cur = _front->_next;
free(_front);
_front = cur;
_size--;
if (_front == NULL)//即队列为空
_rear = NULL;
}
// 打印队列
void Queue::QueuePrint()
{
assert(_front != NULL);
QNode *cur = _front;
cout << "队列内容:";
while (cur != NULL)
{
cout << cur->_val << " ";
cur = cur->_next;
}cout << endl;
}
// 获取队列头部元素 -- 获得队头元素的值
QDataType Queue::QueueFront()
{
assert(_front != NULL);
return _front->_val;
}
// 获取队列队尾元素
QDataType Queue::QueueRear()
{
assert(_front != NULL);
return _rear->_val;
}
// 获取队列中有效元素个数
int Queue::QueueSize()
{
return _size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool Queue::QueueEmpty()
{
if (_front == NULL && _rear == NULL)
return true;
else
return false;
}
/* 再基于上述队列的内容实现栈!!!!!! */
/* 方法1:利用1个队列进行实现 !!!*/
/*
// 插入 - 入栈 (相当于是尾插)
void Stack::stackPush(QDataType val)
{
q->QueuePush(val);
}
// 删除 - 出栈 (相当于是尾删)后进先出
void Stack::stackPop()
{
assert(!q->QueueEmpty());
// 因为上面队列的实现中 QueueFront() 与 QueueRear() 返回的是数值,并不是一个节点,所以就不能通过判断节点是否相等来确定是不是最后一个元素
int num = q->QueueSize();
while (num > 1)
{
q->QueuePush(q->QueueFront());
q->QueuePop();
num--;
}
q->QueuePop();
}
// 元素个数
int Stack::stackSize()
{
return q->QueueSize();
}
// 判空
bool Stack::stackEmpty()
{
return q->QueueEmpty() == true;
}
// 获取栈顶元素 -- 直接返回数据即可,返回刚输入的数据
QDataType Stack::stackTop()
{
return q->QueueRear();
}
// 栈内元素打印
void Stack::stackPrint()
{
assert(!q->QueueEmpty());
//因为队列是先进先出,栈是先进后出,所以利用队列实现栈时,若要实现栈元素的正确打印,就需要将队列中的数据逆序打印,这就和实现队列所用的方法息息相关
//比如,像上面实现队列是依靠单链表实现,这要实现逆序打印就比较麻烦,所以此处为了更简单的打印,没考虑性能,便打算将队列中的数据保存至一个数组里,然
//后逆序打印!当然,如果实现队列使用的是双向链表,这块栈元素打印的实现就会很方便
QDataType *data = (QDataType*)malloc(sizeof(QDataType)*q->QueueSize());
QNode *cur = q->_front;
int i = 0;
while (cur != NULL)
{
*(data + i) = cur->_val;
cur = cur->_next;
i++;
}
cout << "栈内元素:";
for (i = q->QueueSize() - 1; i >= 0; i--)
cout << *(data + i) << " ";
cout << endl;
free(data);
}
*/
/* 方法2:利用2个队列进行实现 */
// 插入 - 入栈 (相当于是尾插)
void Stack::stackPush(QDataType val)
{
if (!q->QueueEmpty())
q->QueuePush(val);
else
q2->QueuePush(val);
}
// 删除 - 出栈 (相当于是尾删)后进先出
void Stack::stackPop()
{
if (q->QueueEmpty() && q2->QueueEmpty())
return;
if (!q->QueueEmpty() && q2->QueueEmpty())//q非空,q2为空,即将q中除队尾的其他元素存至q2,然后q再 pop 最后一个元素,即实现 栈pop
{
// 因为上面队列的实现中 QueueFront() 与 QueueRear() 返回的是数值,并不是一个节点,所以就不能通过判断节点是否相等来确定是不是最后一个元素
int num = q->QueueSize();
while (num > 1)
{
q2->QueuePush(q->QueueFront());
q->QueuePop();
num--;
}
q->QueuePop();
}
else if (q->QueueEmpty() && !q2->QueueEmpty())//q为空,q2非空,同理,即将q2中除队尾的其他元素存至q,然后q2再 pop 最后一个元素,即实现 栈pop
{
// 因为上面队列的实现中 QueueFront() 与 QueueRear() 返回的是数值,并不是一个节点,所以就不能通过判断节点是否相等来确定是不是最后一个元素
int num = q2->QueueSize();
while (num > 1)
{
q->QueuePush(q2->QueueFront());
q2->QueuePop();
num--;
}
q2->QueuePop();
}
}
// 元素个数
int Stack::stackSize()
{
return q->QueueSize() + q2->QueueSize();
}
// 判空
bool Stack::stackEmpty()
{
return q->QueueEmpty() == true && q2->QueueEmpty() == true;
}
// 获取栈顶元素 -- 直接返回数据即可,返回刚输入的数据
QDataType Stack::stackTop()
{
if (q->QueueEmpty() && q2->QueueEmpty())
return NULL;
if (!q->QueueEmpty() && q2->QueueEmpty())
return q->QueueRear();
else if (q->QueueEmpty() && !q2->QueueEmpty())
return q2->QueueRear();
}
// 栈内元素打印
void Stack::stackPrint()
{
if (q->QueueEmpty() && q2->QueueEmpty())
return;
if (!q->QueueEmpty())
{
QDataType *data = (QDataType*)malloc(sizeof(QDataType)*q->QueueSize());
QNode *cur = q->_front;
int i = 0;
while (cur != NULL)
{
*(data + i) = cur->_val;
cur = cur->_next;
i++;
}
cout << "栈内元素:";
for (i = q->QueueSize() - 1; i >= 0; i--)
cout << *(data + i) << " ";
cout << endl;
free(data);
}
else if (!q2->QueueEmpty())
{
QDataType *data = (QDataType*)malloc(sizeof(QDataType)*q2->QueueSize());
QNode *cur = q2->_front;
int i = 0;
while (cur != NULL)
{
*(data + i) = cur->_val;
cur = cur->_next;
i++;
}
cout << "栈内元素:";
for (i = q2->QueueSize() - 1; i >= 0; i--)
cout << *(data + i) << " ";
cout << endl;
free(data);
}
}
void test()
{
/* 将队列与利用队列实现的栈相同输入输出下的结果进行对比 */
cout << "实验队列结果如下:" << endl;
Queue q1;
/* 实验入队操作 */
q1.QueuePush(1);
q1.QueuePush(2);
q1.QueuePush(3);
q1.QueuePush(4);
q1.QueuePrint();// 1 2 3 4
/* 实验出队操作 -- 先进先出 */
q1.QueuePop();
q1.QueuePrint();// 2 3 4
q1.QueuePop();
q1.QueuePrint();// 3 4
//q1.QueuePop();
//q1.QueuePrint();// 4
//q1.QueuePop();
//q1.QueuePrint();// 会有警告,因为assert(),且此时队列为空
/* 实验获取队头元素 */
cout << "此时队头元素为:" << q1.QueueFront() << endl;
/* 实验获取队尾元素 */
cout << "此时队尾元素为:" << q1.QueueRear() << endl;
cout << "此时队列元素个数为:" << q1.QueueSize() << endl;
cout << "此时队列是否为空(是为1,否为0):" << q1.QueueEmpty() << endl;
cout << endl;
cout << "以上述队列实现的栈实验结果如下:" << endl;
Stack s;
/* 实验入栈 */
s.stackPush(1);
s.stackPush(2);
s.stackPush(3);
s.stackPush(4);
s.stackPrint();//4 3 2 1
/* 实验出栈 */
s.stackPop();
s.stackPrint();//3 2 1
s.stackPop();
s.stackPrint();//2 1
//s.stackPop();
//s.stackPrint();//1
//s.stackPop();
//s.stackPrint();//到这里会警告,assert()
/* 实验栈顶元素 */
cout << "此时栈顶元素为:" << s.stackTop() << endl;
/* 实验元素个数与判空 */
cout << "此时栈内元素个数为:" << s.stackSize() << endl;
cout << "此时栈是否为空(是为1,否为0):" << s.stackEmpty() << endl;
cout << endl;
}
int main()
{
test();
system("pause");
return 0;
}
(3)运行结果
注意3:在程序中虽然采取了两种栈的实现方式,但两种方式下的运行结果一致,此处就不再分别配图,如上图!
以上为本篇博客内容,若有问题,欢迎与笔者交流!
侵权删~