#pragma once
#pragma once
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define STACK_INIT_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
typedef double SElemType1;
typedef int Status1;
using namespace std;
typedef struct SqStack1
{
SElemType1* top;
SElemType1* base;
int stacksize;
}SqStack1;
Status1 InitStack(SqStack1& S)
{
S.base = (SElemType1*)malloc(STACK_INIT_SIZE * sizeof(SElemType1));
if (!S.base)exit(OVERFLOW); //存储分配失败
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}//InitStack
SElemType1 GetTop1(SqStack1 S, SElemType1& e)
{
if (S.top == S.base) //等价于if(StackEmpty1(S))
return ERROR;
e = *(S.top - 1);
return e;
}//GetTop1
Status1 Push1(SqStack1& S, SElemType1 e)
{//插入元素e为新的栈顶元素
if (S.top - S.base >= S.stacksize) //如果栈满,则追加空间
{
S.base = (SElemType1*)realloc(S.base,
(S.stacksize + STACKINCREMENT) * sizeof(SElemType1));
if (!S.base)exit(OVERFLOW);//存储分配失败
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e; // 可以分解为: *S.top=e; S.top++
return OK;
}//Push1
Status1 Pop1(SqStack1& S, SElemType1& e)
{//若栈不为空,则删除S的栈顶元素,用e返回其值
if (S.top == S.base) //等价于if(StackEmpty1(S))
return ERROR;
e = *--S.top; // 可以分解为: --S.top; e=*S.top;
return OK;
}//Pop1
bool StackEmpty1(SqStack1 S)
{
if (S.top == S.base)
return OK;
else
return ERROR;
}
void Conversion(SqStack1& S)//输入任意一个非负整数,输出与其等值的八进制数
{
InitStack(S);
int num;
SElemType1 x;
cout << "请输入任意一个非负整数: " << endl;
cin >> num;
cout << "将输出与其等值的八进制数: " << endl;
while (num)
{
Push1(S, num % 8);
num /= 8;
}
while (!StackEmpty1(S))
{
Pop1(S, x);
printf("%2d", x);
}
}
Status1 DestoryStack1(SqStack1& S)
{
free(S.base);
return OK;
}
Status1 CheckMatch(string s, SqStack1& opr_stack) {
InitStack(opr_stack);
int i = 0;
int count = 0;
SElemType1 e;
while (i < s.length()) {
if (s[i] == '(' || s[i] == ')' || s[i] == '{' || s[i] == '}' || s[i] == '[' || s[i] == ']') {//如果当前字符是运算符.
switch (s[i]) {
case '(':
count += 1;
Push1(opr_stack, '(');
break;
case '[':
count += 1;
Push1(opr_stack, '[');
break;
case '{':
count += 1;
Push1(opr_stack, '{');
break;
case ')':
if (GetTop1(opr_stack, e) != '(' && !StackEmpty1(opr_stack))
{
cout << "第" << count << "个括号错了哦!" << endl;
return 0;
}
Pop1(opr_stack, e);
break;
case ']':
if (GetTop1(opr_stack, e) != '[' && !StackEmpty1(opr_stack))
{
cout << "第" << count << "个括号错了哦!" << endl;
return 0;
}
Pop1(opr_stack, e);
break;
case '}':
if (GetTop1(opr_stack, e) != '{' && !StackEmpty1(opr_stack))
{
cout << "第" << count << "个括号错了哦!" << endl;
return 0;
}
Pop1(opr_stack, e);
break;
default:break;
}
}
i++;
}
if (StackEmpty1(opr_stack))
return 1;
return 0;
}
double compvalue1(string postexp)
{
int i = 0;
double d, a, b, c, e;
SqStack1 opnd;
InitStack(opnd);
while (postexp[i] != '\0')
{
switch (postexp[i])
{
case'+':
Pop1(opnd, a);
Pop1(opnd, b);
c = a + b;
Push1(opnd, c);
break;
case'-':
Pop1(opnd, a);
Pop1(opnd, b);
c = b-a;
Push1(opnd, c);
break;
case'*':
Pop1(opnd, a);
Pop1(opnd, b);
c = a * b;
Push1(opnd, c);
break;
case'/':
Pop1(opnd, a);
Pop1(opnd, b);
if (a != 0)
{
c = b / a;
Push1(opnd, c);
break;
}
else
{
cout << "除零错误!" << endl;
exit(0); //异常退出
}
break;
default:
d = 0;
while (postexp[i] >= '0' && postexp[i] <= '9')
{
d = 10 * d + postexp[i] - '0';
i++;
}
Push1(opnd, d);
break;
}
i++;
}
GetTop1(opnd, e);
DestoryStack1(opnd);
return e;
}
上面的是头文件 “SqStack1.h”
上面的是头文件 “SqStack.h” 他们的区别就在于,基本的数据类型不一样了,在求后缀表达式的值的那个函数里面。要求数据是double类型的,所以新建了一个头文件。
下面是几个栈的典型问题:
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include"SqStack.h"
int main()
{
string s;
SElemType e;
SqStack S;
SqStack S1;
SqStack S2;
InitStack(S);
cout << "栈为" << (StackEmpty(S) ? "空" : "非空")<<endl;
cout << "依次进栈元素:a,b,c,d,e "<<endl;
Push(S, 'a');
Push(S, 'b');
Push(S, 'c');
Push(S, 'd');
Push(S, 'e');
cout << "栈为" << (StackEmpty(S) ? "空" : "非空");
cout << endl;
cout << "依次出栈元素:";
while (!StackEmpty(S))
{
Pop(S, e);
printf("%2c", e);
}
cout << endl;
cout << "栈为" << (StackEmpty(S) ? "空" : "非空");
cout << endl;
if (DestoryStack(S))
cout << "已释放"<<endl;
else
cout << "未成功释放"<<endl;
cout << "例一、数值转换->";
Conversion(S1);
cout << endl;
cout << "例二、括号匹配的检验->";
cout << "亲,请输入操作式: ";
cin >> s;
CheckMatch(s, S2);
cout << endl;
cout << "20213002624李季鸿" << endl;
system("pause");
return 0;
}
这个是用来测试中缀表达式转换成后缀表达式的例子:
#include <cstring>
#include <stdlib.h>
#include <malloc.h>
#include"SqStack.h"
#include"SqStack1.h"
int main()
{
char exp[] = "(56-20)/(4+2)";
char postexp[STACK_INIT_SIZE];
trans(exp, postexp);
cout <<"中缀表达式: " <<exp << endl;
cout <<"后缀表达式: " <<postexp<<endl;
printf("表达式的值: %g\n", compvalue1(postexp));
cout << "20213002624李季鸿" << endl;
system("pause");
return 0;
}
书上的例3.4:判断一个字符串是否是对称串
bool symmetry(string str)//判断str是否为对称串
{
int i;
SElemType e;
SqStack ptr;//定义顺序栈指针
InitStack(ptr);
for (i = 0; str[i] != '\0'; i++)
{
Push(ptr, str[i]);
}
for (i = 0; str[i] != '\0'; i++)
{
Pop(ptr, e);
if (str[i] != e)
{
DestoryStack(ptr);
return false;
}
DestoryStack(ptr);
return true;
}
}//这个是函数,放到头文件SqStack.h里面的
#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <malloc.h>
#include"SqStack.h"
#include"SqStack1.h"
//判断一个字符串是否为对称串的测试
int main()
{
string array;
cin >> array;
if (symmetry(array))//判断str是否为对称串
{
cout << "此串是对称串";
}
else
cout << "此串不是对称串";
cout << endl;
cout << "20213002624李季鸿" << endl;
system("pause");
return 0;
}//这个是测试,main函数用来测试
下面这个是迷宫问题,总是不出来结果,先把这个烂尾工程放到这吧:
#pragma once
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define STACK_INIT_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
#define M 8
#define N 8
using namespace std;
typedef int Status;
typedef struct
{
int i; //当前方块的行号
int j; //当前方块的列号
int di; //di是下一相邻可走方位的方位号
}BOX; //方块类型
typedef struct
{
BOX data[STACK_INIT_SIZE];
int top; //栈顶指针
}StType; //方块类型
void InitStack(StType*& S)
{
S= (StType*)malloc(STACK_INIT_SIZE * sizeof(StType));
S->top = -1;
}//InitStack
bool GetTop(StType* S, BOX& e)
{
if (S->top ==-1) //等价于if(StackEmpty(S))
return false;
e =S->data[S->top];
return true;
}//GetTop
bool Push(StType*& S, BOX e)
{//插入元素e为新的栈顶元素
if (S->top == STACK_INIT_SIZE - 1) //如果栈满,则追加空间
return false;
S->top ++;
S->data[S->top] = e;
return true;
}
Status Pop(StType*& S, BOX& e)
{//若栈不为空,则删除S的栈顶元素,用e返回其值
if (S->top == -1) //等价于if(StackEmpty(S))
return false;
e = S->data[S->top]; // 可以分解为: --S.top; e=*S.top;
return OK;
}//Pop
bool StackEmpty(StType* S)
{
return(S->top == -1);
}
Status DestoryStack(StType*& S)
{
free(S);
return OK;
}
int mg[M + 2][N + 2] = //构造出一个8X8的数组,外面两层是围墙
{
{1,1,1,1,1,1,1,1,1,1},{1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,0,1,0,1},{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,0,0,1},{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},{1,0,1,1,1,0,1,1,0,1},
{1,1,0,0,0,0,0,0,0,1},{1,1,1,1,1,1,1,1,1,1},
};
bool mgpath(int xi, int yi, int xe, int ye)//求解路径为(xi, yi)--> (xe, ye)
{
BOX path[STACK_INIT_SIZE], e={0,0,0};
int i, j, di, i1, j1, k;
bool find;
StType* st;
InitStack(st);
e.i = xi; e.j = yi; e.di = -1;
//cout << e.i;
Push(st, e);
mg[xi][yi] = -1;
//cout << "666" <<endl;
while (!StackEmpty(st))
{
/* cout << "666" << endl;*/
GetTop(st, e); //取栈顶方块e
/*cout << " 123123 " << endl;*/
i = e.i; j = e.j; di = e.di;
//cout << " 123123 " << endl;
if (i == xe && j == ye) //找到了出口,输出该路径
{
cout << "一条迷宫路径如下: "<<endl;
k = 0;
while (!StackEmpty(st))
{
Pop(st, e); //出栈方块e
path[k++] = e; //将e添加到path数组中
}
while (k >= 1)
{
k--;
cout << "(" << path[k].i << "," << path[k].j << ")" << " ";
if ((k + 2) % 5 == 0) //每输出5个方块后换一行
cout << endl;
}
cout << endl;
DestoryStack(st);
return true;
}
find = false;
while (di < 4 && !find) //找到(i,j)的下一个相邻可走的方块(i1,j1)
{
/* cout << "123" << endl;*/
di++;
switch (di)
{
case 0:i1 = i - 1; j1 = j; break;
case 1:i1 = i ; j1 = j+1; break;
case 2:i1 = i + 1; j1 = j; break;
case 3:i1 = i ; j1 = j-1; break;
}
if (mg[i1][j1] == 0) find = true; //找到一个可走的方块,设置find为真
/*cout << di << endl;*/
}
if (find) //找到一个可走的方块,(i1,j1)
{
/*cout << "123" << endl;*/
st->data[st->top].di = di;
e.i = i1; e.j = j1; e.di = -1;
Push(st, e); //相邻可走方块e入栈
/* cout << "123" << endl;*/
mg[i1][j1] = -1; //将(i1,j1)迷宫值值为-1,避免重复走到该方块
}
else //没有路可走,则退栈
{
/*cout << "123" << endl;*/
Pop(st, e); //将栈顶方块退栈
mg[e.i][e.j] = 0; //让退栈方块的位置变为其他路径可走方块
}
}
DestoryStack(st);
return false; //表示没有路可以走,返回false
}
#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <malloc.h>
//#include"SqStack.h"
//#include"SqStack1.h"
#include"migong.h"
//用栈解决迷宫问题
int main()
{
cout << M << endl;
if (!mgpath(1, 1, M, N))
cout << "该迷宫问题没有解"<<endl;
return 1;
}
——————————————————————————————————————————
下面就是队列了:
首先是头文件:Queue.h
#pragma once
#include<cstdlib>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define STACK_INIT_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
typedef int Status;
typedef int QElemType;
using namespace std;
//---单链队列---队列的链式存储结构
typedef struct QNode {
QElemType data;
struct QNode* next;
}QNode, * QueuePtr;
typedef struct {
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;
// 1.构造一个空队列 Q
Status InitQueue(LinkQueue& Q)
{
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
if (!Q.front)
{
exit(OVERFLOW);
}
Q.front->next = NULL;
return OK;
}
// 2.销毁队列 Q
Status DestoryQueue(LinkQueue& Q)
{
while (Q.front) {
Q.rear = Q.front->next;
free(Q.front);
Q.front = Q.rear;
}
return OK;
}
// 3.插入元素e为新的队尾元素 (入队)
Status EnQueue(LinkQueue& Q, QElemType e)
{
QueuePtr p;
p = (QueuePtr)malloc(sizeof(QNode));
if (!p)
{
exit(OVERFLOW);
}
p->data = e; p->next = NULL;
Q.rear->next = p;
Q.rear = p;
}
// 4.出队
Status DeQueue(LinkQueue& Q, QElemType& e)
{
QueuePtr p;
if (Q.front == Q.rear) //若队为空,返回错误
{
return ERROR;
}
p = (QueuePtr)malloc(sizeof(QNode));
if (!p)
{
exit(OVERFLOW);
}
p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if (Q.rear == p)
{
Q.rear = Q.front; //如果出队的恰好是队尾元素,将队置为空
}
free(p);
return OK;
}
// 5.求队的长度
Status QueueLength(LinkQueue Q)
{
int i = 0;
QueuePtr p;
p = Q.front;
while (Q.rear != p)
{
i++;
p = p->next;
}
return i;
}
// 6.遍历队
Status QueueTraverse(LinkQueue& Q, Status(visit)(QElemType)) //第二个参数是函数名
{
QueuePtr p;
if (!Q.front)
{
cout << "队为空!";
return 0;
}
p = Q.front->next;
cout << "打印队列:\n-------------------------------------------"<<endl;
while (p)
{
visit(p->data);
p = p->next;
}
cout << endl;
return OK;
}
// 7.打印
int PrintElem(QElemType e)
{
printf(" %d |", e);
return OK;
}
// 8.判断队是否为空
Status QueueEmpty(LinkQueue Q)
{
return(Q.rear->next == NULL);
}
// 9.获得队头元素
Status GetHead(LinkQueue Q, QElemType& e)
{
QueuePtr p;
p = Q.front->next;
if (Q.front == Q.rear)
{
return ERROR;
}
e = p->data;
return OK;
}
// 10.清空队
Status ClearQueue(LinkQueue& Q)
{
QueuePtr p, q;
Q.rear = Q.front;
p = Q.front->next;
Q.front->next = NULL;
while (p)
{
q = p;
p = p->next;
free(q);
}
cout << "队已清空!" << endl;
return OK;
}
然后是main函数用来测试基本的功能:
#include<iostream>
#include<malloc.h>
#include<ctime>
#include"Queue.h"
int main() {
LinkQueue Q;//结构体Q
InitQueue(Q);
QElemType e;
srand(time(NULL));
int n;//随机插入队列元素的数目。
cout << "请输入队列随机元素数目:" << endl;
cin >> n;
while (n--)
{
e = rand() % 100;
EnQueue(Q, e);//进队n个元素
}
GetHead(Q, e);
cout << "当前队头元素为:" << e<<endl;
QueueTraverse(Q, PrintElem);
DeQueue(Q, e);
cout << endl << "-----------------队头元素出队后:------------------------" << endl;
GetHead(Q, e);
cout << "当前队头元素为: " << e << endl;
QueueTraverse(Q, PrintElem);
if (!QueueEmpty(Q))
{
cout << "队列非空" << endl;
}
e = rand() % 50;
cout << endl << "入队的元素为" << e << endl;
EnQueue(Q, e);//再次入队
GetHead(Q, e);
cout << "当前队头元素为:" << e << endl;
QueueTraverse(Q, PrintElem);
//清空
cout << endl << "-----------清空队列--------"<<endl;
DestoryQueue(Q);
QueueTraverse(Q, PrintElem);
return 0;
}
代码运行结果是:
下面是循环队列的一些基本操作(Queue-circle.h头文件里面的):
#pragma once
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define MAXQSIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
typedef int Status;
typedef int QElemType;
using namespace std;
//------------循环队列------------队列的顺序存储结构
typedef struct QNode {
QElemType *base;//初始化的动态分配存储空间
int front; //头指针,若队列不动,指向队列头元素
int rear; //尾指针,若队列不动,指向队列尾元素的下一个位置
}SqQueue;
//------------循环队列的基本操作的算法描述------------
//1.构造一个空队列
Status InitQueue(SqQueue& Q)
{
Q.base = (QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
if (!Q.base)
{
exit(OVERFLOW);
}
Q.front = Q.rear = 0;
return OK;
}
//2.返回队列的元素个数,即队列的长度
int QueueLength(SqQueue Q)
{
return(Q.rear - Q.front + MAXQSIZE) % MAXQSIZE; //这个公式太妙了!!!
}
//3. 插入元素e为Q的新的队尾元素
Status EnQueue(SqQueue& Q, QElemType e)
{
if ((Q.rear + 1) % MAXQSIZE == Q.front) //rear+1追上front
{
return ERROR; //队列满
}
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE; //rear指向下一个(尾元素后面一个)位置
return OK;
}
//4. 若队列不为空,则删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
Status DeQueue(SqQueue& Q, QElemType& e)
{
if (Q.front == Q.rear) //front追上rear
{
return ERROR;
}
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
return OK;
}
下面是用队列实现杨辉三角,在头文件中增加了杨辉三角的一个函数
//打印杨辉三角
void YangHuiTriangle(int N) {
SqQueue q;
InitQueue(q);
int n, i, x, temp;
EnQueue(q, 1); //第一行元素入队
for (n = 2; n <= N; n++)
{
EnQueue(q, 1); //第n行第一个元素入队
for (i = N; i >= n; i--) //给数字间加空格,打印出金字塔形状
{
printf(" "); // N为打印的行数,n为每行的元素个数
}
for (i = 1; i <= n - 2; i++)
{ //利用队中第n-1行元素产生第n行的中间n-2个元素并入队
DeQueue(q, temp); //出队元素赋给temp
printf("%6d", temp); //打印第n-1行的元素
GetHead(q,x);
temp = temp + x; //利用第n-1行元素产生第n行元素
EnQueue(q, temp); //可以利用画图理解
}
DeQueue(q, x);
printf("%6d", x); //打印n-1行最后一个元素
EnQueue(q, 1);
printf("\n");
}
while (!QueueEmpty(q)) { //打印最后一行
DeQueue(q, x);
printf("%6d", x);
}
}
因为函数都封装好了,主函数的调用就很简单了:
#include<iostream>
#include<malloc.h>
#include<cstdlib>
#include<malloc.h>
#include<ctime>
//#include"Queue1.h"
using namespace std;
//#include"Queue.h"
#include"Queue-circle.h"
int main() {
int n;
cout << "你想输出几行杨辉三角?" << endl;
cin >> n;
YangHuiTriangle(n);
cout << endl;
cout << "\n\n\n\n20213002624李季鸿,终于搞出来了!!!" << endl;
system("pause");
return 0;
}