【栈与队列】数据结构的C++实现 基础知识自学(一)

使用教材:《数据结构C++语言版》(第三版) 清华大学出版社

练习PAT过程中发现自己的C++和数据结构都很烂,是以决定先打好基础。

栈和队列

这两个数据结构都属于线性表,所以放在里面的元素也都具有线性次序。

(一)栈 Stack

1.栈的定义

栈是存放数据对象的一种特殊容器,其中的数据元素按照线性的逻辑次序排列,故也可定义首、末元素。

栈只有一段可以操作,即栈顶(stack top),另外一端不能,不能操作的一端被称为盲端,也叫栈底(stack buttom)

栈是先进后出结构,LIFO(last in first out)

2.栈的接口功能

———— 栈的接口功能 ————

操作接口功能
size()报告栈的规模
empty()判断栈是否为空【返回布尔变量】
push(e)将e压入栈顶
pop()删除栈顶对象
top()取出栈顶对象
3.栈的典型应用

使用栈的头文件:

#include <stack>

定义栈:

stack<int> stk;
3.1 逆序输出
3.1.1 进制转换

例1.给定任意十进制整数n,将其转换为X进制的表示形式。

主要在这个例子中关注栈的调用方式:
1)头文件的正确引用;

#include <stack>

2)声明一个栈的方式;

stack<char> stk;  //尖括号里是数据类型,一般为char ,因为char 比较容易向其他数据形式转换

3)当栈作为参数的时候如何书写;

stack<char> &S

————这就是教材上的代码,我加了主函数让它可以进行测试而已————

#include <iostream>
#include <stack> 
using namespace std;

void convert(stack<char> &S,int n,int base);
//数位转换函数:将十进制的n转化为base进制的数 
int main()
{
	printf(" 请输入您想转换的进制:  ");
    	int base;
 	    scanf("%d",&base);
 	
 	printf("请输入要被转换的数字: ");
 	    int n;
 	    scanf("%d",&n);
 	    
 	printf(" 转换结果为: ");
 	    stack<char> S;
	    convert(S,n,base);
	while(S.empty()==false)
	{
		printf("%c",S.top());//引用栈顶对象 
		S.pop();//删除栈顶对象 
	}
	
	return 0; 
	
 } 

void convert(stack<char> &S,int n,int base)
{
	static char digit[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
	while(n>0)
	{
		int remainder = (int)(n%base);//余数是第几位,就对应到哪里 
		S.push(digit[remainder]);//压入栈,这样就能做到最后输出个位 
		n/=base;//n除base 
	}
}
3.1.2 括号匹配

例2:使用栈来进行括号匹配的思路非常简单:遇到左括号压栈,遇到有括号弹栈,看弹出的是否匹配——如果弹出的括号不匹配,或者最后栈非空,则都不算能够匹配的上。

#include <iostream>
#include <stack>
#include <string>
using namespace std;


bool bean(char exp[],int lo,int hi)//表达式括号匹配检查,可以兼顾三种括号 
{
	stack<char> S;//使用栈记录已发现但尚未匹配的左括号
	for(int i=lo;i<=hi;i++)//逐一检查当前字符 
	{
		switch(exp[i])
		{
			case'(':case'[':case'{':S.push(exp[i]);break;
			case')':if((S.empty())||(S.pop()!='(')) return false;break;
			case']':if((S.empty())||('['!=S.pop())) return false;break;
			case'}':if((S.empty())||('{'!=S.pop())) return false;break;
			default:break;//非括号字符一律忽略 
		}
	 } 
	return S.empty();//若栈为空,则匹配;否则不匹配 
}

int main()
{
	printf("请输入字符串: ");
		char exp[100];
		scanf("%s",exp);
	int hi=0;
	int i=0;
	while(exp[i]!='\0')
	{
		hi=hi+1;
		i++;
		}	
	bool result=bean(exp,0,hi);
	if(bean==false)
		printf("\n不匹配");
	else
		printf("\n匹配"); 
	
	return 0;
}
3.1.3 表达式求值

先序后序表达式转换的问题,因为需要输入符号优先级表,懒得输入所以没做。
总归就是符号或数字压栈的问题。

4 试探回溯法与剪枝
4.1 N皇后问题

这个问题基于一个矩阵,放置皇后的过程就像是“占住一个格子”,皇后的势力范围是它所在的同一行,同一列,还有同一条对角线,请问在一个N*N矩阵里,最多可以放置多少个皇后,这就是经典的N皇后问题。

#include <iostream>
#include <stack>
using namespace std;

struct Queen{//皇后类 
	int x,y;//皇后在棋盘上的位置坐标
	Queen(int xx=0,int yy=0):x(xx),y(yy){};
	bool operator==(Queen const&q)const
	{
		return (x==q.x)//行冲突
				||(y==q.y)//列冲突 
				||(x+y==q.x+q.y)//沿正对角线冲突 
				||(x-y==q.x-q.y) //沿反对角线冲突 
	}
	bool operator!=(Queen const&q)const{return !(*this == q);}
	} 
};

void placeQueen(int N)//N皇后算法 
{
	stack<Queen> solu;//存放(部分)解的栈
	Queen q(0,0);//从原点位置出发放置皇后
	do{
		if(N <= solu.size()||N<=q.y) //N出界,则
		{
			q=solu.pop());//回溯一行,继续试探下一列 
			q.y++;
		 } 
		else
		{
			while((q.y<N)&&(0<=solu.find(q)))//通过与已有皇后的比对
			{
				q.y++;
				nCheck++;
			}
			if(N>q.y)
			{
				solu.push(q);
				if(N <= solu.size())
					nSolu++;
					q.x++;
					q.y=0;
			}
		}
	} while((0<q.x)||(q.y<N))
}

int main()
{
	
}
3.1.3 迷宫寻径

(二) 队列 FIFO

定义:基本形式与栈相同。最重要的特征是“先进后出”,即,如果将队列的一端设置为可插入,则只能从另外一端删除。

队头: front
队尾: rear

队首出,队尾入。
为便于记忆,可以将这个过程记作排队打饭,加入队伍的时候排在队尾,分配资源的时候从队头开始分配。

头文件:

#include <queue>

定义队列:

queue <int> q;

———— 队列函数一览 ————

操作接口功能
size()报告队列的规模
empty()判断队列是否为空【返回布尔变量】
enqueue(e)将e加入队尾
dequeue()删除队首对象
front()取出队首对象
常见的队列应用
1.循环分配器

多用户排队等待资源分配时,队列适合处理这样的问题。先到先排队,先排队先得到服务。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值