数据结构C语言版:栈和队列之栈

3.1栈

 3.1.1 抽象数据类型栈的定义

        栈是限定仅在表尾进行插入或者删除操作的线性表。表尾端称为栈顶(top),表头端称为栈底(bottom),不含元素的空表称为空栈。

        栈又称为后进先出的线性表,他的特点类似于铁路调度站

退栈的第一个元素为栈顶元素。

3.1.2栈的表示和实现

        和线性表类似,栈也有两种存储表示方法。

        顺序栈:栈的顺序存储结构,利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素(与顺序表一样),同时附设指针top知识栈顶元素在顺序栈中的位置。

        栈在使用过程中所需最大空间难以估计,合理做法为不够再扩充(类似于线性表动态扩充)

        顺序栈的定义:

//---------------------------顺序栈结构体定义 ----------------------------------
typedef  struct {
	SElemType* base;//栈底指针,始终指向栈底位置
	SElemType* top;//栈顶指针,初始值指向栈底,所以top=base是栈空的标志
//新元素入栈,top指针增1,所以非空栈栈顶指针始终再栈顶元素的下一个位置
	int    stacksize;//栈当前最大容量
}SqStack ;

        顺序栈基本操作:

#include<iostream>
using namespace std;
typedef int SElemType;
typedef int Status;
#define MAXSIZE 100//顺序栈存储空间的初始分配量
#define STACKINCREMENT 10;
#define OK 1;
//顺序栈结构体定义 
typedef int Status;
typedef int SElemType;

typedef  struct {
	SElemType* base;//指针构造销毁之后base的值为null
	SElemType* top;
	int    stacksize;
}SqStack;




//初始化栈 
Status InitStack(SqStack& S)
{
	S.base = (SElemType*)malloc(MAXSIZE * sizeof(SElemType));//这里创建了一个SElemType(栈)型结点并把地址赋值给栈底指针
	if (!S.base)
	{
		exit(OVERFLOW);//存储分配失败返回错误值
	}
	S.top = S.base;//初始栈底等于栈顶
	S.stacksize = MAXSIZE;//设置最大容量
	return OK;
}

//将元素e入栈 
Status Push(SqStack& S, SElemType e)//传入栈的地址和元素e
{
	if (S.top - S.base >= S.stacksize)
	{
		//S.base = (SElemType*)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(SElemType));//如果栈满,追加存储空间
	}
	if (!S.base)
	{
		exit(OVERFLOW);//存储分配失败返回错误值
	}
	*S.top = e;//e赋值给当前栈顶
	S.top++;//栈顶指针+1
	return 0;
}

//出栈,用e返回出栈元素 
Status Pop(SqStack& S, SElemType& e)
{
	if (S.top == S.base)
	{
		return 0;//空栈,返回错误值
	}
	S.top--;//栈顶指针-1
	e = *S.top;//
	return OK;
}

//返回栈顶元素 
Status GetTop(SqStack S, SElemType& e)
{
	if (S.top == S.base)
	{
		return 0;//空栈
	}
	e = *(S.top - 1);//栈顶元素在栈顶指针-1的位置
	return OK;
}

//清空栈,变为空栈 
void  Clear(SqStack& S)
{
	if (S.base)
	{
		S.top = S.base;//脑袋等于屁股直接删干净
		cout << "清空结束" << endl;
	}
}

//遍历栈元素 (从栈底到栈顶) 
void Traverse(SqStack S)
{
	if (S.base == NULL)
	{
		cout << "栈不存在" << endl;
	}
	if (S.top == S.base)
		printf("空栈\n");
	SElemType* P;//设置一个指针P
	P = S.top;//P指向栈顶指针
	while (P > S.base)//只要P大于栈底指针
	{
		P--;
		std::cout << *P << endl;
	}
}

//进制转换函数,将十进制数dec转化为n进制数,并输出转换后结果 
void Convert(SqStack& S, int dec, int n)
{
	SElemType e;//整形变量e用来存放中间值

	while (dec) //十进制数不为0时
	{
		int i = dec % n;
		Push(S, i);//将最后一位数传入栈
		dec = dec / n;
	}
	cout << "转换结果为:" << endl;;
	while (S.top != S.base) //栈不为空时
	{
		cout << Pop(S, e);//按顺序出栈
	}

}
Status EmptyStack(SqStack& S)//判断栈是否为空
{
	if (S.top == S.base)
	{
		return OK;
	}
	else
		return 0;
}

int main(void)
{
	SElemType e;
	SqStack st;
	InitStack(st);//初始创建一个栈
	int c = 0;
	while (c != 7)
	{
		cout << endl << "1. 入栈";
		cout << endl << "2. 出栈";
		cout << endl << "3. 读栈顶";
		cout << endl << "4. 遍历栈";
		cout << endl << "5. 清空顺序栈";
		cout << endl << "6. 进制转换";
		cout << endl << "7. 退出";
		cout << endl << "选择功能(1~6):";
		cin >> c;
		switch (c)
		{
		case 1:
		{
			cout << "输入入栈元素" << endl;
			cin >> e;
			Push(st, e);
			break;
		}
		case 2:
		{
			cout << "元素:" << Pop(st, e) << "已经出栈" << endl;;
			break;
		}
		case 3:
		{
			cout << "栈顶元素为:" << GetTop(st, e) << endl;
			break;
		}
		case 4:
		{
			Traverse(st);
			break;
		}
		case 5:
		{
			Clear(st);
			break;
		}
		case 6:
		{
			int dec, n;
			cout << " 请输入待转换的十进制数:" << endl;
			cin >> dec;
			cout << " 请输入转换的进制:" << endl;
			cin >> n;
			Convert(st, dec, n);
			break;

		}
		case 7:break;
		}
	}
}

        链栈基本操作:

#include<iostream>
#include <stdlib.h>
#include<string.h>
#include<malloc.h>
#include<string>
using namespace std;

typedef char SElemType;

typedef int Status;//一般Status表示成功与失败
#define OK 1;
#define FALSE 0;

//链栈结构体定义 注意这里是链栈而不是线性栈
typedef  struct SNode
{
	SElemType  data;	//存放数据的数据域
	SNode* next;		//存放下一个结点地址的指针域
}SNode, * LinkStack;


//将元素e入栈 
Status Push(LinkStack& S, SElemType e)
{
	SNode* P;//生成一个SNode形的指针
	P = (LinkStack)malloc( sizeof(SNode));//这个指针指向一个新的SNode类新的结点
	P->data = e;//这个结点的数据域上的指针指向传进来的元素e
	P->next = S;//新结点插向栈顶,这里新节点的P指针的地址域指向了栈顶S指针
	S = P;//S这个头指针重新指向栈顶
	//注意,链栈的指针是一直指向栈顶的,通过从栈顶指向下一个来实现栈的先进后出!!!
	return OK;
}

//出栈,用e返回出栈元素 
Status Pop(LinkStack& S, SElemType& e)
{
	if (S == NULL)
	{
		cout << "栈不存在" << endl;
	}
	else
	{
		e = S->data;		//把头指针(指向栈顶)的数据域赋值给e
		SNode* P;			//生成一个新的SNode形的指针
		P = S;				//让这个P指针指向栈顶
		S = S->next;		//头指针的位置向栈底移动一位
		free(P);			//删除P结点,实现“出栈“
	}
	return e;
}

//返回栈顶元素 
Status GetTop(LinkStack S, SElemType& e)
{
	if (S != NULL)
	{
		return S->data;//只要栈不为空直接输出栈顶头指针所致数据域
	}
	else
		cout << "数组为空" << endl;
}

//清空栈,变为空栈 
void  Clear(LinkStack& S)
{
	SNode* P;//新建一个P指针用来遍历一遍栈
	while (S)//当s栈不为空
	{
		P = S;//指针P指向栈顶准备开始
		S = P->next;//头指针下移动
		free(P);//删除P指针实现释放栈顶
		//不断重复此过程
	}
	cout << "删除结束" << endl;
}

//遍历栈元素 (从栈顶到栈底) 
void Traverse(LinkStack S)
{
	SNode* P;//新建一个P指针用来遍历一遍栈
	P = S;//指针P指向栈顶准备开始
	cout << "当前栈为" << endl;
	while (P != NULL)
	{
		cout << P->data << endl;//输出指针P当前所指的数据域
		P = P->next;//指针P下移,准备输出下一位
	}
	cout << "遍历结束" << endl;
}

//回文是指正读反读均相同的字符序列,如"acdca"、"dceecd"均是回文,但"book"不是回文。
//试写一个算法判定输入的字符串是否为回文,并将结果输出,例如:"acdca"是回文 
int HuiWen(LinkStack s, string str)
{
	int i;
	char c;//用来接受出栈的
	for (i = 0; i < (str.length() / 2); i++)//字符前半段入栈
	{
		Push(s, str[i]);
	}
	if (str.length() % 2)	//奇数长度字符串跳过中间元素
	{
		i++;
	}
	for (i=0; i < str.length(); i++) {
		Pop(s, c);//前半段出栈与后半段比较
		if (c != str[i])
		{
			return false;
		}
	}

}

int main(void)
{
 
	LinkStack st = NULL;//新建了一个叫st的栈并且为空
	int st_num = 0;
	SElemType e;
	int c = 0;
	while (c != 7)
	{
		cout << endl << "1. 入栈";
		cout << endl << "2. 出栈";
		cout << endl << "3. 读栈顶";
		cout << endl << "4. 遍历栈";
		cout << endl << "5. 清空顺序栈";
		cout << endl << "6. 回文判断";
		cout << endl << "7. 退出";
		cout << endl << "选择功能(1~6):";
		cin >> c;
		switch (c)
		{
		case 1:
		{
			cout << "请输入进栈元素总数" << endl;
			cin >> st_num;
			for (int i = 1; i <= st_num; i++)
			{
				cout << "请输入第" << i << "个元素" << endl;
				cin >> e;
				if (Push(st, e))
				{
					cout << "入栈成功" << endl;
				}
				else
					cout << "入栈失败" << endl;
			}

			break;
		}
		case 2:
		{
			cout << "元素:" << (char)Pop(st, e) << "已成功出栈" << endl;;

			break;
		}
		case 3:
		{
			cout << "栈顶元素为:" << GetTop(st, e) << endl;
			break;
		}
		case 4:
		{//遍历栈
			Traverse(st);
			break;
		}
		case 5:
		{
			Clear(st);
			break;
		}
		case 6:
		{
			LinkStack s = NULL;
			char str[100];
			cout << "输入数组" << endl;
			cin >> str;
			if (HuiWen(s, str))
				cout << str << "是回文。" << endl;
			else
				cout << str << "不是回文。" << endl;

			break;
		}
		case 7:
			break;
		}
	}
}

        括弧检测:

int main()
{
	LiStack L;
	InitStack(L);//初始化
	cout << "请输入你想检测的括号(输入'-'结束程序)\n";
	char x;
	cin >> x;
	while (x != '-') {
		if (x == '(' || x == '[' || x == '{') {
			Push(L, x);
			cin >> x;
		}
		if (x == ')' || x == ']' || x == '}') {
			char a;
			a = GetTop(L);
			//cout << a;
			if ((x == ')' && a == '(') || (x == ']' && a == '[') || (x == '}' && a == '{')) {
				char b;
				int c = Pop(L, b);
				cout << "左括号\t\t" << b << "\t匹配成功!\n";
				cin >> x;
			}
			else {
				cout << "右括号\t\t" << x << "\t匹配失败!\n";
				return 0;
			}
		}
	}
	if (L == NULL) {
		cout << "全部括号匹配成功!\n";
	}
	else {
		char y;
		y = GetTop(L);
		cout << "左括号\t\t" << y << "\t匹配失败!\n";
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值