数据结构 | 栈(顺序栈+链栈)的基本实现

学习教材:王红梅《数据结构——从概念到C++实现》、严蔚敏《数据结构

学习课程:青岛大学王卓《数据结构与算法基础》

分类专栏:数据结构与算法(C++)

目录

前言

正文

1.栈的介绍

1.1 栈的概述

1.2 栈的特点

2.栈的基本实现及设计

2.1 顺序栈设计

2.1.1 数据类型设计

2.1.2 算法设计

(1)构造函数

(2)析构函数

(3)入栈操作

(4)创建指定长度的顺序栈

(5)判空操作

(6)出栈操作

(7)取出栈顶元素(不删除)

(8)输出顺序栈长度

(9)遍历打印顺序栈当前元素

2.2 链栈设计

2.2.1 数据类型设计

2.2.2 算法设计

(1)构造函数

(2)析构函数

(3)入栈操作

(4)创建指定长度的链栈

(5)出栈操作

(6)输出链栈长度

(7)判空操作

(8)取出栈顶元素(不删除)

(9)遍历打印链栈当前元素

2.3 菜单设计

2.3.1 主页面菜单设计

2.3.2 二级页面菜单设计

3.全部代码(分文件编写)

SeqStack.h

SeqStack.cpp

LinkedStack.h

LinkedStack.cpp

my_Menu.h

my_Menu.cpp

main.cpp


前言

        最近刚在学习《数据结构与算法》,单纯地跟课、看书觉得并不能很好的掌握好这些知识点,所以决定尝试将学习的知识点归纳总结,也将其进行代码实现,强化对知识点的理解。即作为笔记、实践,又作为我的思路分享。因为初学,难免有不正确、不恰当之处,敬请指正!

正文

1.栈的介绍

1.1 栈的概述

        (stack)是限定仅在表的一端进行插入和删除操作的线性表,允许插入和删除的一端称为栈顶(stack top),另一端为栈底(stack bottom),不含任何数据元素的栈称为空栈。跟据存储结构的不同,栈同样可以分为顺序栈和链栈两种。

1.2 栈的特点

        栈可以理解为一种功能受限的线性表,因此栈中的元素同样具有线性关系。但因为其只能通过一端进行元素的插入和删除,入栈、出栈具有顺序性,因此栈还具有“后进先出”的特性。

        举个简单的例子:一把枪我们填入子弹后,如果要将最底下(也就是最先放入)的子弹取出来的话,我们需要把在它之后填入的子弹按照顺序取出,即“后进先出”。

2.栈的基本实现及设计

2.1 顺序栈设计

2.1.1 数据类型设计

        首先定义一个模板类SeqStack,其成员变量有两个,一个是存储数据的数组data,一个是存储顺序栈栈顶元素序号的变量top,为保证数据的安全性,均将权限设为私有。为实现数据的一系列操作,又创建了相应的成员函数,将其权限设置为公有,作为成员变量的接口,供测试者使用。

#define MAXSIZE 100 // 顺序栈最多可以存储多少个元素,可按要求更改

template<typename DataType>
class SeqStack
{
public:
	SeqStack();						// 构造函数,初始化一个空栈
	~SeqStack() {};					// 析构函数
	void CreateSeqStack();
	void Push(DataType x); 			// 入栈操作,将元素x入栈
	DataType Pop();					// 出栈操作,将栈顶元素弹出,并返回弹出的元素值
	DataType GetTop();				// 取出栈顶元素(并不删除)
	int Length();					// 求顺序栈长度
	int Empty();					// 判空操作
	void PrintStack();			    // 遍历打印,按照出栈顺序打印

private:
	DataType data[MAXSIZE];         // 存储元素的数据
	int top;                        // 存储栈顶元素的下标
};
2.1.2 算法设计
(1)构造函数

        即将顺序栈进行初始化,只需将栈顶指针top置为-1即可。

template<typename DataType>
SeqStack<DataType>::SeqStack()
{
	this->top = -1;
}
(2)析构函数

        顺序栈为静态存储分配,在顺序栈变量退出作用域时,将自动释放顺序栈所占存储空间,因此无须销毁,析构函数为空。

(3)入栈操作

       首先应判断栈是否为满,即top+1是否等于 MAXSIZE 。若未满, 在栈中插入元素n只需要将栈顶位置加1,然后在data[top]的位置填入元素x。

template<typename DataType>
void SeqStack<DataType>::Push(DataType x)
{
	if (this->top+1 == MAXSIZE) throw"上溢";
	this->data[top + 1] = x;
	this->top++;
}
(4)创建指定长度的顺序栈

        创建长度为n的顺序栈,即按照输入顺序,对一个空栈进行n次入栈。

template<typename DataType>
void SeqStack<DataType>::CreateSeqStack()
{
	int num, value;
	cout << "请输入要入栈的元素个数:";
	cin >> num;
	cout << "请输入要入栈的元素数值:";
	for (int i = 0; i < num; i++)
	{
		cin >> value;
		this->data[i] = value;
		this->top++;
	}
}
(5)判空操作

        判空操作只需要判断顺序栈类成员函数top是否等于-1,即 this->top==-1。

template<typename DataType>
int SeqStack<DataType>::Empty()
{
	if (this->top==-1)		
		return 1;
	else
		return 0;
}
(6)出栈操作

        将一个元素从顺序栈中删除,即出栈,首先应判断栈是否为空,即this->Empty()是否等于1。若栈非空,出栈操作只需取出栈顶元素,然后top再减1。

template<typename DataType>
DataType SeqStack<DataType>::Pop()
{
	DataType y;
	if (this->Empty() == 1) throw"下溢";
	y = this->data[top];
	this->top--;
	return y;
}
(7)取出栈顶元素(不删除)

        取栈顶元素只是将top位置的栈顶元素取出并返回,并不改变栈本身。

template<typename DataType>
DataType SeqStack<DataType>::GetTop()
{
	DataType y;
	if (this->Length() == 0) throw"下溢";
	// if (this->Empty == 1) throw"下溢";
	y = this->data[top];
	return y;

}
(8)输出顺序栈长度

        输出顺序栈的长度,就是将top加1后再返回。

template<typename DataType>
int SeqStack<DataType>::Length()
{
	return this->top+1;
}
(9)遍历打印顺序栈当前元素

        通过前面所写的Length(),得到顺序栈的长度,使用循环,从栈底开始遍历打印。

template<typename datatype>
void SeqStack<datatype>::PrintStack()
{
	int length = this->Length();

	if (length > 0)
	{
		for (int i = 0; i < length; i++)
			cout <<this->data[i] << " ";
		cout << endl;
	}
	else
		cout << "顺序栈为空" << endl;
}

2.2 链栈设计

2.2.1 数据类型设计

        首先使用结构体创建LinkedNode数据类型,定义了结点,包括指针域next和数据域data。随后定义链栈类LinkedStack,其成员变量为LinkedNode类型的指针top,为保证数据的安全性,将权限设为私有。为实现数据的一系列操作,又创建了相应的成员函数,将其权限设置为公有,作为成员变量的接口,供测试者使用。

// 定义了LinkNode结点
template<typename DataType>
struct LinkNode {
	DataType data;//数据域
	LinkNode<DataType>* next;//指针域 
};

template<typename DataType>
class LinkedStack
{
public:
	LinkedStack() { top = NULL; }		// 构造函数,初始化一个空栈
	~LinkedStack();					// 析构函数
	void CreateLinkedStack();
	void Push(DataType x); 			    // 入栈操作,将元素x入栈
	DataType Pop();					    // 出栈操作,将栈顶元素弹出,并返回弹出的元素值
	DataType GetTop();				    // 取出栈顶元素(并不删除)
	int Length();					    // 求顺序栈长度
	int Empty();					    // 判空操作
	void PrintStack();		            // 遍历打印,按照出栈顺序打印

private:
	LinkNode<DataType>* top;
};
2.2.2 算法设计
(1)构造函数

        链栈不带头结点,初始化一个空链栈只需将栈顶指针top置空。

template<typename DataType>
LinkedStack<DataType>::LinkedStack()
 { 
    top = NULL; 
}
(2)析构函数

        链栈为动态存储分配,在链栈变量退出作用域前要释放链栈的存储空间。

template<typename DataType>
LinkedStack<DataType>::~LinkedStack()
{
	LinkNode<DataType>* p = top;
	while (this->top)
	{
		top = top->next;
		delete p;
		p = top;
	}
}
(3)入栈操作

        链栈的插入只需处理栈顶的情况,先申请一个新结点s,在其数据域中存入入栈元素、指针域存入top的地址,再使top=s。

template<typename DataType>
void LinkedStack<DataType>::Push(DataType x)
{
	// 申请一个数据域为x的结点s
	LinkNode<DataType>* s = new LinkNode<DataType>;
	if (!s)
	{
		cout << "分配内存失败";
		return;
	}
	s->data = x;
	s->next = top;
	top = s;
}
(4)创建指定长度的链栈

        创建长度为n的链栈,即按照输入顺序,对一个空链栈进行n次入栈。

template<typename DataType>
void LinkedStack<DataType>::CreateLinkedStack()
{
	this->top = nullptr;
	LinkNode<DataType>* s = nullptr;

	int num, value;
	cout << "请输入要创建的链栈长度:";
	cin >> num;
	cout << "请输入入栈的元素数值:";

	for (int i = 0; i < num; i++) 
	{
		cin >> value;
		LinkNode<DataType>* newNode = new LinkNode<DataType>;
		newNode->data = value;
		newNode->next = top;
		top = newNode;
	}
}
(5)出栈操作

        链栈的删除操作只需处理栈顶的情况,创建一个临时结点temp,使temp=top,将栈顶元素取出,随后使top=top->next,使栈顶指针top指向下一结点。将temp的数据域取出存于新定义的变量y中,随后释放结点temp(原栈顶元素)。

template<typename DataType>
DataType LinkedStack<DataType>::Pop()
{
	if (this->Empty() == 1) throw"下溢";

	LinkNode<DataType>* temp = top;
	top = top->next;
	int y = temp->data;
	delete temp;
	return y;
}
(6)输出链栈长度

        定义了变量length用于计数,在循环中遍历链栈,直至到栈底元素为止,判定的依据为结点的next域为空。

template<typename DataType>
int LinkedStack<DataType>::Length()
{
	int length = 0;
	LinkNode<DataType>* current = this->top;
	while (current != nullptr) {
		current = current->next;
		length++;
	}
	return length;
}
(7)判空操作

        使用前面所写的Length()函数进行判空。

template<typename DataType>
int LinkedStack<DataType>::Empty()
{
	if (this->Length() == 0)
	{
		return 1;
	}
	else
		return 0;
}
(8)取出栈顶元素(不删除)

        取栈顶元素只需返回栈顶指针top所指结点的数据域,并不修改栈顶指针。

template<typename DataType>
DataType LinkedStack<DataType>::GetTop()
{
	if (this->Empty() == 1) throw"下溢";

	return top->data;
}
(9)遍历打印链栈当前元素
template<typename DataType>
void LinkedStack<DataType>::PrintStack()
{
	LinkNode<DataType>* current = this->top;

	cout << "当前链表中的元素为:";
	while (current != nullptr) {
		cout << current->data << " ";
		current = current->next;
	}
	cout << endl;
}

2.3 菜单设计

2.3.1 主页面菜单设计

        主页面菜单(即一级菜单)使用switch-case语句实现。先定义一个choice_one变量,将输入的数值存入,通过判断choice_one来进入不同二级页面或退出。

int choice_one;
	choice_one = -1;
	while (choice_one != 0)
	{
		cout << "栈示例:" << endl;
		cout << "1. 顺序栈功能实现" << endl;
		cout << "2. 链栈功能实现" << endl;
		cout << "0. 退出" << endl;
		cout << "请选择:" << endl;
		cin >> choice_one;
		system("cls");

		switch (choice_one)
		{
		case 1:// 
			SeqStackMenu();
			system("pause");
			system("cls");
			break;

		case 2:// 
			LinkedStackMenu();
			system("pause");
			system("cls");
			break;

		case 0: // 0.退出
			cout << "欢迎下次使用!" << endl;
			system("pause");
			return 0;
			break;

		default:
			cout << "非法输入,请重新选择!" << endl;
			system("pause");
			system("cls");
			break;

		}
	}
2.3.2 二级页面菜单设计

       因为二级菜单内容较多,并未和一级菜单写在一个文件中,而是采取了分文件编写的思想,创建了my_menu.cpp和My_menu.h,将二级菜单存入其中。顺序栈和链栈的功能菜单分别写成函数,然后再直接在一级菜单中进行调用。为区分开,二级菜单定义了新的变量choice_two,用来存储二级菜单的选择数值。

// 顺序栈的功能菜单
void SeqStackMenu()
{
	SeqStack<int> Seq;
	/* 注意重置choice_two的值,否则将会再次进入会变为0,无法开始循环 */
	int choice_two = -1;

	while (choice_two)
	{
		cout << "顺序栈示例:" << endl;
		cout << "1. 创建指定长度的顺序栈" << endl;
		cout << "2. 将指定元素入栈" << endl;
		cout << "3. 弹出栈顶元素" << endl;
		cout << "4. 输出栈顶元素数值" << endl;
		cout << "5. 输出顺序栈的长度" << endl;
		cout << "6. 遍历打印顺序栈" << endl;
		cout << "0. 返回上一级菜单" << endl;
		cout << "请选择:" << endl;
		cin >> choice_two;

		switch (choice_two)
		{
		case 1:
			try
			{
				Seq.CreateSeqStack();
				cout << "顺序栈的元素为:(从栈底开始遍历)" << endl;
				Seq.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 2:
			try
			{
				int value;
				cout << "请输入将要入栈的元素数值" << endl;
				cin >> value;
				Seq.Push(value);
				cout << "顺序栈的元素为:(从栈底开始遍历)" << endl;
				Seq.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 3:
			try
			{
				int value = Seq.Pop();
				cout << "弹出的栈顶元素的数值为:" << value << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 4:
			try
			{
				cout << "当前顺序栈的栈顶元素数值为:" << Seq.GetTop() << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 5:
			try
			{
				cout << "当前顺序栈的长度为:" << Seq.Length() << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 6:
			try
			{
				cout << "当前顺序栈的元素为:(从栈底开始遍历)" << endl;
				Seq.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 0:
			cout << "退出顺序栈功能菜单!" << endl;
			break;

		default:
			cout << "非法输入,请重新选择!" << endl;
			system("pause");
			system("cls");
			break;
		}
	}
}


// 链栈的功能菜单
void LinkedStackMenu()
{
	LinkedStack<int> Link;
	int choice_two = -1;

	while (choice_two)
	{
		cout << "链栈示例:" << endl;
		cout << "1. 创建指定长度的链栈" << endl;
		cout << "2. 将指定元素入栈" << endl;
		cout << "3. 弹出栈顶元素" << endl;
		cout << "4. 输出栈顶元素数值" << endl;
		cout << "5. 输出链栈的长度" << endl;
		cout << "6. 遍历打印链栈" << endl;
		cout << "0. 返回上一级菜单" << endl;
		cout << "请选择:" << endl;
		cin >> choice_two;

		switch(choice_two)
		{
		case 1:
			try
			{
				Link.CreateLinkedStack();
				Link.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 2:
			try
			{
				int value;
				cout << "请输入将入栈的元素数值:";
				cin >> value;
				Link.Push(value);
				Link.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 3:
			try
			{
				int value = Link.Pop();
				cout << "弹出的栈顶元素数值为:" << value << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 4:
			try
			{
				cout << "栈顶元素的数值为:" << Link.GetTop() << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 5:
			try
			{
				int length = Link.Length();
				cout << "当前链表的长度为:" << length << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 6:
			try
			{
				Link.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 0:
			cout << "退出链栈功能菜单!" << endl;
			break;

		default:
			cout << "非法输入,请重新选择!" << endl;
			system("pause");
			system("cls");
			break;
		}
	}

}

3.全部代码(分文件编写)

SeqStack.h

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

#ifndef SeqStack_H
#define SeqStack_H


#define MAXSIZE 100 // 顺序栈最多可以存储多少个元素,可按要求更改

template<typename DataType>
class SeqStack
{
public:
	SeqStack();						// 构造函数,初始化一个空栈
	~SeqStack() {};					// 析构函数
	void CreateSeqStack();
	void Push(DataType x); 			// 入栈操作,将元素x入栈
	DataType Pop();					// 出栈操作,将栈顶元素弹出,并返回弹出的元素值
	DataType GetTop();				// 取出栈顶元素(并不删除)
	int Length();					// 求顺序栈长度
	int Empty();					// 判空操作
	void PrintStack();			// 遍历打印,按照出栈顺序打印

private:
	DataType data[MAXSIZE];
	int top;
};


#endif

SeqStack.cpp

#include "SeqStack.h"

//*****************************************************
//函数名:SeqStack
//函数功能:构造函数,初始化一个空栈
//输入参数:
//	无
//输出参数:
//	无
//******************************************************
template<typename DataType>
SeqStack<DataType>::SeqStack()
{
	this->top = -1;
}

//*****************************************************
//函数名:CreateSeqStack
//函数功能:创建一个指定长度的顺序栈
//输入参数:
//	无
//输出参数:
//	无
//******************************************************
template<typename DataType>
void SeqStack<DataType>::CreateSeqStack()
{
	int num, value;
	cout << "请输入要入栈的元素个数:";
	cin >> num;
	cout << "请输入要入栈的元素数值:";
	for (int i = 0; i < num; i++)
	{
		cin >> value;
		this->data[i] = value;
		this->top++;
	}
}

//*****************************************************
//函数名:Push
//函数功能:入栈操作,将元素x入栈
//输入参数:
//	DataType,x,即将入栈的元素数值
//输出参数:
//	无
//******************************************************
template<typename DataType>
void SeqStack<DataType>::Push(DataType x)
{
	if (this->top+1 == MAXSIZE) throw"上溢";
	this->data[top + 1] = x;
	this->top++;
}

//*****************************************************
//函数名:Pop
//函数功能:出栈操作,将栈顶元素弹出,并返回弹出的元素值
//输入参数:
//	无
//输出参数:
//	DataType,弹出元素的数值
//******************************************************
template<typename DataType>
DataType SeqStack<DataType>::Pop()
{
	DataType y;
	if (this->Empty() == 1) throw"下溢";
	y = this->data[top];
	this->top--;
	return y;
}

//*****************************************************
//函数名:GetTop
//函数功能:取出栈顶元素(并不删除)
//输入参数:
//	无
//输出参数:
//	DataType,栈顶元素的数值
//******************************************************
template<typename DataType>
DataType SeqStack<DataType>::GetTop()
{
	DataType y;
	if (this->Length() == 0) throw"下溢";
	// if (this->Empty == 1) throw"下溢";
	y = this->data[top];
	return y;

}

//*****************************************************
//函数名:Length
//函数功能:输出栈的长度
//输入参数:
//	无
//输出参数:
//	int,栈的长度
//******************************************************
template<typename DataType>
int SeqStack<DataType>::Length()
{
	return this->top+1;
}

//*****************************************************
//函数名:Empty
//函数功能:判断栈是否为空
//输入参数:
//	无
//输出参数:
//	1,代表栈为空;0,代表栈非空
//******************************************************
template<typename DataType>
int SeqStack<DataType>::Empty()
{
	if (this->top==-1)		
		return 1;
	else
		return 0;
}

//*****************************************************
//函数名:PrintStack
//函数功能:遍历打印栈
//输入参数:
//	无
//输出参数:
//	无
//******************************************************
template<typename datatype>
void SeqStack<datatype>::PrintStack()
{
	int length = this->Length();

	if (length > 0)
	{
		for (int i = 0; i < length; i++)
			cout <<this->data[i] << " ";
		cout << endl;
	}
	else
		cout << "顺序栈为空" << endl;
}

LinkedStack.h

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

#ifndef LinkedStack_H
#define LinkedStack_H

template<typename DataType>
struct LinkNode {
	DataType data;//数据域
	LinkNode<DataType>* next;//指针域 
};

template<typename DataType>
class LinkedStack
{
public:
	LinkedStack() { top = NULL; }		// 构造函数,初始化一个空栈
	~LinkedStack();					// 析构函数
	void CreateLinkedStack();
	void Push(DataType x); 			    // 入栈操作,将元素x入栈
	DataType Pop();					    // 出栈操作,将栈顶元素弹出,并返回弹出的元素值
	DataType GetTop();				    // 取出栈顶元素(并不删除)
	int Length();					    // 求顺序栈长度
	int Empty();					    // 判空操作
	void PrintStack();		            // 遍历打印,按照出栈顺序打印

private:
	LinkNode<DataType>* top;
};


#endif

LinkedStack.cpp

#include "LinkedStack.h"

// 析构函数
template<typename DataType>
LinkedStack<DataType>::~LinkedStack()
{
	LinkNode<DataType>* p = top;
	while (this->top)
	{
		top = top->next;
		delete p;
		p = top;
	}
}

//*****************************************************
//函数名:CreateLinkedStack
//函数功能:创建一个指定长度的链栈
//输入参数:
//	无
//输出参数:
//	无
//******************************************************
template<typename DataType>
void LinkedStack<DataType>::CreateLinkedStack()
{
	this->top = nullptr;
	LinkNode<DataType>* s = nullptr;

	int num, value;
	cout << "请输入要创建的链栈长度:";
	cin >> num;
	cout << "请输入入栈的元素数值:";

	for (int i = 0; i < num; i++) 
	{
		cin >> value;
		LinkNode<DataType>* newNode = new LinkNode<DataType>;
		newNode->data = value;
		newNode->next = top;
		top = newNode;
	}
}

//*****************************************************
//函数名:Push
//函数功能:入栈操作,将元素x入栈
//输入参数:
//	DataType,x,即将入栈的元素数值
//输出参数:
//	无
//******************************************************
template<typename DataType>
void LinkedStack<DataType>::Push(DataType x)
{
	// 申请一个数据域为x的结点s
	LinkNode<DataType>* s = new LinkNode<DataType>;
	if (!s)
	{
		cout << "分配内存失败";
		return;
	}
	s->data = x;
	s->next = top;
	top = s;
}

//*****************************************************
//函数名:Pop
//函数功能:出栈操作,将栈顶元素弹出,并返回弹出的元素值
//输入参数:
//	无
//输出参数:
//	DataType,弹出元素的数值
//******************************************************
template<typename DataType>
DataType LinkedStack<DataType>::Pop()
{
	if (this->Empty() == 1) throw"下溢";

	LinkNode<DataType>* temp = top;
	top = top->next;
	int y = temp->data;
	delete temp;
	return y;
}

//*****************************************************
//函数名:GetTop
//函数功能:取出栈顶元素(并不删除)
//输入参数:
//	无
//输出参数:
//	DataType,栈顶元素的数值
//******************************************************
template<typename DataType>
DataType LinkedStack<DataType>::GetTop()
{
	if (this->Empty() == 1) throw"下溢";

	return top->data;
}

//*****************************************************
//函数名:Empty
//函数功能:判断栈是否为空
//输入参数:
//	无
//输出参数:
//	1,代表栈为空;0,代表栈非空
//******************************************************
template<typename DataType>
int LinkedStack<DataType>::Empty()
{
	if (this->Length() == 0)
	{
		return 1;
	}
	else
		return 0;
}

//*****************************************************
//函数名:Length
//函数功能:输出栈的长度
//输入参数:
//	无
//输出参数:
//	int,栈的长度
//******************************************************
template<typename DataType>
int LinkedStack<DataType>::Length()
{
	int length = 0;
	LinkNode<DataType>* current = this->top;
	while (current != nullptr) {
		current = current->next;
		length++;
	}
	return length;
}

//*****************************************************
//函数名:PrintStack
//函数功能:遍历打印栈
//输入参数:
//	无
//输出参数:
//	无
//******************************************************
template<typename DataType>
void LinkedStack<DataType>::PrintStack()
{
	LinkNode<DataType>* current = this->top;

	cout << "当前链表中的元素为:";
	while (current != nullptr) {
		cout << current->data << " ";
		current = current->next;
	}
	cout << endl;
}

my_Menu.h

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

#ifndef my_Menu_H
#define my_Menu_H

void SeqStackMenu();
void LinkedStackMenu();


#endif

my_Menu.cpp

#include "my_Menu.h"
#include "SeqStack.cpp"
#include "LinkedStack.cpp"


//*****************************************************
//函数名:SeqStackMenu
//函数功能:顺序栈的功能菜单
//输入参数:
//	无
//输出参数:
//	无
//******************************************************
void SeqStackMenu()
{
	SeqStack<int> Seq;
	/* 注意重置choice_two的值,否则将会再次进入会变为0,无法开始循环 */
	int choice_two = -1;

	while (choice_two)
	{
		cout << "顺序栈示例:" << endl;
		cout << "1. 创建指定长度的顺序栈" << endl;
		cout << "2. 将指定元素入栈" << endl;
		cout << "3. 弹出栈顶元素" << endl;
		cout << "4. 输出栈顶元素数值" << endl;
		cout << "5. 输出顺序栈的长度" << endl;
		cout << "6. 遍历打印顺序栈" << endl;
		cout << "0. 返回上一级菜单" << endl;
		cout << "请选择:" << endl;
		cin >> choice_two;

		switch (choice_two)
		{
		case 1:
			try
			{
				Seq.CreateSeqStack();
				cout << "顺序栈的元素为:(从栈底开始遍历)" << endl;
				Seq.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 2:
			try
			{
				int value;
				cout << "请输入将要入栈的元素数值" << endl;
				cin >> value;
				Seq.Push(value);
				cout << "顺序栈的元素为:(从栈底开始遍历)" << endl;
				Seq.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 3:
			try
			{
				int value = Seq.Pop();
				cout << "弹出的栈顶元素的数值为:" << value << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 4:
			try
			{
				cout << "当前顺序栈的栈顶元素数值为:" << Seq.GetTop() << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 5:
			try
			{
				cout << "当前顺序栈的长度为:" << Seq.Length() << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 6:
			try
			{
				cout << "当前顺序栈的元素为:(从栈底开始遍历)" << endl;
				Seq.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 0:
			cout << "退出顺序栈功能菜单!" << endl;
			break;

		default:
			cout << "非法输入,请重新选择!" << endl;
			system("pause");
			system("cls");
			break;
		}
	}
}


//*****************************************************
//函数名:LinkedStackMenu
//函数功能:链栈的功能菜单
//输入参数:
//	无
//输出参数:
//	无
//******************************************************
void LinkedStackMenu()
{
	LinkedStack<int> Link;
	int choice_two = -1;

	while (choice_two)
	{
		cout << "链栈示例:" << endl;
		cout << "1. 创建指定长度的链栈" << endl;
		cout << "2. 将指定元素入栈" << endl;
		cout << "3. 弹出栈顶元素" << endl;
		cout << "4. 输出栈顶元素数值" << endl;
		cout << "5. 输出链栈的长度" << endl;
		cout << "6. 遍历打印链栈" << endl;
		cout << "0. 返回上一级菜单" << endl;
		cout << "请选择:" << endl;
		cin >> choice_two;

		switch(choice_two)
		{
		case 1:
			try
			{
				Link.CreateLinkedStack();
				Link.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 2:
			try
			{
				int value;
				cout << "请输入将入栈的元素数值:";
				cin >> value;
				Link.Push(value);
				Link.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 3:
			try
			{
				int value = Link.Pop();
				cout << "弹出的栈顶元素数值为:" << value << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 4:
			try
			{
				cout << "栈顶元素的数值为:" << Link.GetTop() << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 5:
			try
			{
				int length = Link.Length();
				cout << "当前链表的长度为:" << length << endl;
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 6:
			try
			{
				Link.PrintStack();
				system("pause");
				system("cls");
				break;
			}
			catch (const char* s)
			{
				cout << s << endl;
				system("pause");
				system("cls");
				break;
			}
		case 0:
			cout << "退出链栈功能菜单!" << endl;
			break;

		default:
			cout << "非法输入,请重新选择!" << endl;
			system("pause");
			system("cls");
			break;
		}
	}

}

main.cpp

#include<iostream>
#include "SeqStack.cpp"
#include "LinkedStack.cpp"
#include "my_Menu.h"
using namespace std;

int main()
{
	int choice_one;
	choice_one = -1;
	while (choice_one != 0)
	{
		cout << "栈示例:" << endl;
		cout << "1. 顺序栈功能实现" << endl;
		cout << "2. 链栈功能实现" << endl;
		cout << "0. 退出" << endl;
		cout << "请选择:" << endl;
		cin >> choice_one;
		system("cls");

		switch (choice_one)
		{
		case 1:// 
			SeqStackMenu();
			system("pause");
			system("cls");
			break;

		case 2:// 
			LinkedStackMenu();
			system("pause");
			system("cls");
			break;

		case 0: // 0.退出
			cout << "欢迎下次使用!" << endl;
			system("pause");
			return 0;
			break;

		default:
			cout << "非法输入,请重新选择!" << endl;
			system("pause");
			system("cls");
			break;

		}
	}

	system("plase");
	return 0;
}

初学数据结构与算法,若有不正确之处,敬请指正啦~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值