若栈采用顺序存储方式存储,现两栈共享空间V[1..m],top[i]代表第i个栈( i =1,2)栈顶(该位置不存储对应栈数据),栈1的底在v[1],栈2的底在V[m],则栈满的条件是top[1]-1=top[2]
当两个栈共享一个数组空间时,它们的增长方向是相反的:
栈 1 从数组起始位置(索引 1)开始,向上增长(即栈顶指针top[1]递增)。
栈 2 从数组末尾位置(索引 m)开始,向下增长(即栈顶指针top[2]递减)。
栈满条件推导
栈 1 的有效数据范围:从V[1]到V[top[1]-1]。
例如,当栈 1 为空时,top[1] = 1(无有效数据);当压入一个元素后,top[1] = 2,数据存于V[1]。
栈 2 的有效数据范围:从V[m]到V[top[2]+1]。
例如,当栈 2 为空时,top[2] = m(无有效数据);当压入一个元素后,top[2] = m-1,数据存于V[m]。
栈满的临界条件:
当两个栈的有效数据区域相邻且无间隙时,数组被占满。此时:
栈 1 的最高有效位置为top[1]-1。
栈 2 的最低有效位置为top[2]+1。
若两者相邻,则有:top[1]-1 = top[2]+1 – 1(相邻位置索引差 1),即top[1]-1 = top[2]。
若用大小为6的数组来实现循环队列,且当前front和rear的值分别为0和4。当从队列中删除两个元素,再加入两个元素后,front和rear的值分别为2和0



元素个数=(rear−front+队列容量)%队列容量
设C语言数组Data[m+1]作为循环队列SQ的存储空间, front为队头指针,rear为队尾指针,则执行出队操作的语句为front=(front+1)%(m+1)
为解决计算机主机与打印机之间速度不匹配问题,通常设置一个打印数据缓冲区,主机将要输出的数据依次写入该缓冲区,而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是队列
(SWPU-DS)若串S=“software”,其子串的个数是37。(空串+1)
空串是否计入子串需根据定义判断。若题目未明确包含空串,则总子串数为所有非空长度的子串数之和,即:
总子串数=∑nk=1(n−k+1)=n(n+1)/2;
设栈S和队列Q的初始状态均为空,元素abcdefg依次进入栈S。若每个元素出栈后立即进入队列Q, 且7个元素出队的顺序是bdcfeag, 则栈S的容量至少是3
队列先进先出,栈后进后出

一个栈的入栈序列为1,2, 3,…,n,出栈序列是P1,P2,P3,…,Pn。若P2=3, 则可能取值的个数是n-1
对空栈S进行Push和Pop操作,入栈序列为a,b,c,d,e, 经过Push、Push、Pop、Push、Pop 、Push、Push、Pop操作后得到的出栈序列是b,c,e


已知循环队列存储在一维数组A[0…n-1] 中,且队列非空时front和rear分别指向队首元素和队尾元素。若初始时队列为空,且要求第一个进入队列的元素存储在A[0]处,则初始时 front和 rear 的值分别是0, n-1


9 8
7 6 5 4
3 2
1
若栈Sl中保存整数,栈S2中保存运算符,函数F( )依次执行下述各步操作:
从Sl 中依次弹出两个操作数a和b.
从S2 中弹出一个运算符op.
执行相应的运算b op a.
将运算结果压入Sl 中.
假定Sl中的操作数依次是5, 8, 3, 2 (2 在栈顶),S2中的运算符依次是*、-、+ (+在栈顶)。调用 3次F( )后,Sl栈顶保存的值是15
与表达式x+y*(z-u)/v等价的后缀表达式是xyzu-*v/+

有一个 12*12 阶对称矩阵M,将其上三角部分的元素mi,j(1<=i<=j<=12)按行优先存入C语言的一维数组N 中,元素m6,6在N 中的下标是50
. 总下标公式(下标从 0 开始)下标=(i−1)×(2n−i)/2+(j−1)
若数组下标从 1 开始,只需在上述公式结果上加 1;

二维数组A按行优先方式存储,每个元素占用1个存储单元。若元素A[0][0] 的存储地址是100, A [3] [3] 的存储地址是220, 则元素A[5] [5] 的存储地址是300
Address(A[i][j])=Base+(i×n+j)×Size
Base=100(A [0][0] 的地址)A [3] [3]=>n=39=>A[5][5]
Size=1(每个元素占 1 个存储单元)
若采用三元组表存储结构存储稀疏矩阵M, 则除三元组表外,下列数据中还需要保存的是仅I、III
I. M的行数 III. M 的列数
–
链队基本操作入队出队
Status InitQueue(LinkQueue &Q) {
Q.front = Q.rear = new QNode;
Q.front->next = NULL;
return OK;
}
Status EnQueue(LinkQueue &Q, QElemType e) {
QueuePtr p;
p = new QNode; // 创建新节点
p->data = e; // 存储数据元素
p->next = NULL;
Q.rear->next=p; // 将新节点链接到队尾
Q.rear=p; // 更新队尾指针指向新节点
return OK;
}
Status DeQueue(LinkQueue &Q, QElemType &e) {
QueuePtr p;
if (Q.front == Q.rear)// 判断队列是否为空
return ERROR; // 队列为空时返回错误
p = Q.front->next; // p指向队头元素(front的下一个节点)
e = p->data; // 获取队头元素的值
Q.front->next=p->next; // 队头指针指向下一个节点
if (Q.rear == p)// 如果删除的是最后一个元素
Q.rear=Q.front; // 重置队尾指针指向头节点
delete p;// 释放被删除节点的内存
return OK;
}
字符串匹配算法
typedef int Status;
#define MAXSTRLEN 255 //用户可在255以内定义最长串长
typedef char SString[MAXSTRLEN+1]; //0号单元存放串的长度
//BF算法
int Index(SString S, SString T, int pos)
{
int i = pos;
int j = 1;
while(i <= S[0] && j <= T[0])
{
if(S[i]==T[j])
{
++i;
++j;
}
else
{
i = i - j + 2;
j = 1;
}
}
if (j > T[0])
return i - T[0];
else
return 0;
return 0;
}
编写函数实现顺序栈的初始化、出栈、入栈运算。
Status iniStack(Sqstack &S) //初始化栈
{
S.base=(char*)malloc(stack_INIT_SIZE*sizeof(SElemType));
S.top=S.base;
S.stacksize=stack_INIT_SIZE;
return 1;
}//InitStack
Status push(Sqstack &S,SElemType x)
{
if(S.top-S.base>=S.stacksize) return ERROR;
*S.top++=x;
return OK;
}
Status pop(Sqstack &S,SElemType &e)
{
if(S.top==S.base) return ERROR;
e=*--S.top;
return OK;
}
循环队列出队入队
用一个数组表示循环队列,请编写算法实现循环队列的初始化、入队和出队操作。
输入时:第一行输入队列数据空间容量,第二行依次输入5个待插入元素值,第三行再依次输入5个待插入元素值。
输出时:第一行和最后一行输出循环队列元素值及其下标(元素值(下标)),若中途出现队空或队满,则应给出相应提示。
接口参数: Q是循环队列, N 是队列数组空间容量, x是入队元素, e用于接收出队元素的值
void InitQ(SqQueue &Q,int N){
Q.base = (int *)malloc(N*sizeof(int));
Q.front = Q.rear=0;
}
void AddQ(SqQueue &Q, int x ){
if((Q.rear+1)%N==Q.front){printf("Queue Full\n");
return;
}
Q.base[Q.rear] = x;// 将元素放入队尾位置
Q.rear = (Q.rear+1)%N;// 队尾指针循环后移
}
Status DeleteQ(SqQueue &Q,int &e){
if(Q.front == Q.rear){
printf("Queue Empty\n");
return 0;
}
e=Q.base[Q.front];// 获取队头元素的值
Q.front =(Q.front+1)%N; // 队头指针循环后移
return 1;
}
下面程序可实现表达式中括号匹配检查,约定只有‘()’、'[]’、'{}’三种括号。请将以下程序补充完整。
Status push(Sqstack &S,SElemType x) //x入栈S
{
if (S.top - S.base >= S.stacksize) {
S.base = (SElemType *)realloc(S.base, (S.stacksize + stackINCREMENT) * sizeof(SElemType));
if (!S.base) return ERROR;
S.top = S.base + S.stacksize;
S.stacksize += stackINCREMENT;
}
*S.top++ = x;
return OK;
}
Status pop(Sqstack &S,SElemType &e);//从S栈出栈1次元素放入e
Status Compare(char s[]) //s为表达式
{
Sqstack S;
SElemType e;
Status flag = TRUE;
int i = 0;
iniStack(S);
while(s[i] != '#' && flag == TRUE )
{
switch(s[i]){
case '(':
case '[':
case '{':push(S,s[i]);break;
case ')': if(pop(S,e)==ERROR || e != '(')//如果是(
flag = FALSE;break;
case ']': if(pop(S,e)==ERROR || e != '[')//如果是[
flag = FALSE;break;
case '}': if(pop(S,e)==ERROR || e != '{')//如果是{
flag = FALSE;break;
}
i++;
}
if(flag == TRUE && s[i] == '#' && S.top == S.base)
return TRUE;
else
return FALSE;
}
许多大学生报名参与大运会志愿者工作。其中运动场引导员需要男女生组队,每组一名男生加一名女生,男生和女生各自排成一队,依次从男队和女队队头各出一人配成小组,若两队初始人数不同,则较长那一队未配对者调到其他志愿者队。现要求写一算法模拟上述配对问题,你需要用队列操作实现上述算法。
Status EnQueue(SqQueue& Q, QElemType e) //入队
{ /* 插入元素e为Q的新的队尾元素 */
if ((Q.rear + 1) % MAX_QSIZE == Q.front) return ERROR;
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAX_QSIZE;
return OK;
}
Status DeQueue(SqQueue& Q, QElemType& e) //出队
{ /* 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR */
if (Q.front == Q.rear) return ERROR;
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAX_QSIZE;
return OK;
}
void Partner(int num) { //num是志愿者总人数
InitQueue(Mdancers); //男生队列初始化
InitQueue(Fdancers); /女生队列初始化
QElemType p;
for (int i = 0; i < num; i++) //依次将志愿者根据其性别入队
{
cin >> p.name >> p.sex;
if (p.sex == 'F')
EnQueue(Fdancers, p); //插入女队
else
EnQueue(Mdancers, p); //插入男队
}
if (QueueEmpty(Fdancers) || QueueEmpty(Mdancers))
cout << "配对失败!" << endl;
else
{
cout << "配对成功小组:" << endl;
while (!QueueEmpty(Fdancers) &&!QueueEmpty(Mdancers)) { //依次输出男女志愿者的姓名
DeQueue(Fdancers, p); //女生出队
cout << p.name << " "; //输出出队女生姓名
DeQueue(Mdancers, p); //男生出队
cout << p.name << endl; //输出出队男生姓名
}
}
}
编写程序实现银行排队叫号系统,采用链队列作为存储结构。
Status InitLinkQueue(LinkQueue &Q) {
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
if (!Q.front) {
exit(OVERFLOW);
}
Q.front->next = NULL;
return OK;
}
Status EnLinkQueue(LinkQueue &Q, QElemType e) {
QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
if (!p) {
exit(OVERFLOW);
}
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
return OK;
}
Status DeLinkQueue(LinkQueue &Q, QElemType &e) {
if (Q.front == Q.rear) {
return ERROR;
}
QueuePtr p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if (Q.rear == p) {
Q.rear = Q.front;
}
free(p);
return OK;
}
Status QueueEmpty(LinkQueue Q) {
return Q.front == Q.rear ? TRUE : FALSE;
}
后缀式求值(一位整型操作数版)
我们人类习惯于书写“中缀式”,如 3 + 5 * 2 ,其值为13。 (p.s. 为什么人类习惯中缀式呢?是因为中缀式比后缀式好用么?)
而计算机更加习惯“后缀式”(也叫“逆波兰式”,Reverse Polish Notation)。上述中缀式对应的后缀式是: 3 5 2 * +
现在,请对输入的后缀式进行求值。为了简化输入处理和运算,运算数(操作数)不超过300个且均为1位正整数,运算符(操作符)仅有+ – * /(加减乘除)四种,运算数和运算符之间没有空格间隔,且题目保证运算的中间结果和最终结果都在整型范围内。
但是注意,题目输入的后缀式可能错误,例如:
1234+- 错误,缺少运算符
123+-* 错误,缺少运算数
122-/ 错误,除数为0
题目保证以上三种错误不会同时发生。
#include<bits/stdc++.h>
using namespace std;
stack<int> ans;
int main()
{
int n;
cin >> n;
while(n --) {
string s;
cin >> s;
int num = 0, way = 0;
bool flag = 0;
for(int i = 0; i < s.size(); i ++) {
if(s[i] >= '0' && s[i] <= '9') {
num ++;
}
if(s[i] == '+' || s[i]== '-' ||s[i] == '*' || s[i] == '/') {
way ++;
}
}
if(num - way != 1) {
cout << "Expression Error!" << endl;
continue;
}
for(int i = 0; i < s.size(); i ++) {
if (s[i] >= '0' && s[i] <= '9') {
ans.push(s[i] - '0');
}
if (s[i] == '+') {
int a = ans.top();
ans.pop();
int b = ans.top();
ans.pop();
ans.push(a + b);
}
else if (s[i] == '-') {
int a = ans.top();
ans.pop();
int b = ans.top();
ans.pop();
ans.push(b - a);
}
else if (s[i] == '*') {
int a = ans.top();
ans.pop();
int b = ans.top();
ans.pop();
ans.push(b * a);
}
else if (s[i] == '/') {
int a = ans.top();
ans.pop();
int b = ans.top();
ans.pop();
if (a) {
ans.push(b / a);
}
else{
cout << "Division By Zero!" << endl;
flag = 1;
break;
}
}
}
if (flag) {
continue;
}
cout << ans.top() << endl;
}
return 0;
}