温故而知新 -> 数据结构 ->利用 队列 实现 栈 -> 程序实现2_利用类

温故而知新 -> 数据结构 ->利用 队列 实现 栈 -> 程序实现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:在程序中虽然采取了两种栈的实现方式,但两种方式下的运行结果一致,此处就不再分别配图,如上图!

以上为本篇博客内容,若有问题,欢迎与笔者交流!
侵权删~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值