后进先出
栈的结构体定义及基本操作。
#define MaxSize 50
typedef struct {
int data[MaxSize];//栈中存放数据类型为整型
int top;//栈顶指针
}Stack;
初始化
这里初始化时是将栈顶指针指向-1,有些则是指向0,因此后续入栈出栈的代码略微有点区别
void InitStack(Stack& S) {//初始化栈
S.top = -1;
}
判断栈是否为空
int IsEmpty(Stack S) {//判断栈是否为空
if (S.top == -1)
return 1;
else
return 0;
}
压栈操作
int Push(Stack& S, int x) {//压栈操作
if (S.top == MaxSize - 1)//若栈满则无法压栈
return 0;
S.top++;
S.data[S.top] = x;
return 1;
}
出栈操作
int Pop(Stack& S, int& x) {//出栈操作
if (S.top == -1)//若栈空则无法出栈
return 0;
x = S.data[S.top];
S.top--;
return 1;
}
读取栈顶元素
这里将出栈的元素用x接收
int GetTop(Stack S, int& x) {//读取栈顶元素
if (S.top == -1)//若栈空则无栈顶元素
return 0;
x = S.data[S.top];
return 1;
}
当然以上的是顺序栈,还有链栈,和单链表类似,带头结点处为栈头,另外一边为栈底,入栈出栈都在头结点处进行,方便操作。
int central_symmetry(LinkList L, int n) {
char S[n / 2];//定义字符型数组来作为一个栈
int i;//定义栈顶指针
LNode* p = L->next;//定义遍历指针
//对称轴左边字符依次入栈
for (i = 0; i < n / 2; i++) {
S[i] = p->data;
p = p->next;
}
i--;//变量 i 返回栈顶位置
if (n % 2 == 1) {//若字符数为奇数则 p 向后遍历一步,因为最中间字符不需考虑
p = p->next;
}
while (p != NULL) {//对称轴右边字符依次与栈顶元素比对
if (p->data == S[i]) {//与栈顶元素相等则 p 继续遍历与下一出栈元素比较
i--;//出栈
p = p->next;//继续遍历
}
else//若不等,则说明 n 个字符不对称,直接返回 0
return 0;//非中心对称
}
return 1;//若正常跳出循环,则证明 n 个字符对称,返回 1
}
int BracketsCheck(char a[]) {
Stack S;
InitStack(S);
char x;
for (int i = 0; a[i] != '\0'; i++) {
switch (a[i]) {
case'('://若数组元素为左括号,则压栈继续遍历
push(S, a[i]);
break;
case'[':
push(S, a[i]);
break;
case')'://若元素为右括号,则需考虑是否有左括号与之配对
if (IsEmpty(S) {
return 0;//若栈空,则说明无左括号与之配对
}
else {
Pop(S, x);
if (x != '(') {//若栈不为空,则判断栈顶元素与当前括号是否配对
return 0;
}
//配对上了
break;
}
case']':
if (IsEmpty(S)) {
return 0;
}
else {
Pop(S, x);
if (x != '[') {
return 0;
}
break;
}
default://若数组元素不是括号则直接继续遍历
break;
}
}
if (IsEmpty(S)) {//若数组遍历完成后栈为空,则证明所有左括号全部配对成功
return 1;
}
else {//若栈不为空,则证明有左括号未配对
retun 0;
}
}
两个栈,需要两个栈顶指针,这里定义了top数组,一个top[0],一个top[1]
#define MaxSize 50
typedef struct{
int data[MaxSize];
int top[2];//一个top[0],一个top[1]指针
}DStack;
初始化
void InitDStack(DStack& S) {
S.top[0] = -1;//初始化 S1 栈顶指针
S.top[1] = MaxSize;//初始化 S2 栈顶指针
}
入栈
int push(int i, int x) {
if (i < 0 || i>1) {
return 0;//若 i 的输入不合法,则无法入栈
}
if (S.top[1] - S.top[0] == 1) {//若存储空间已满,则无法进行入栈操作
return 0;
}
switch (i) {
case 0:// S1 栈顶指针上移后入栈
S.top[0]++;
S.data[S.top[0]] = x;
//S.data[++S.top[0]] = x;
break;
case 1:// S2 栈顶指针下移后入栈
S.top[1]--;
S.data[S.top[1]] = x;
//S.data[--S.top[1]] = x;
break;
}
return 1;
}
出栈
int pop(int i, int& x) {
if (i < 0 || i>1) {
return 0;
}
if (S.top[0] == -1 || S.top[1] == MaxSize) {//空栈
return 0;
}
switch (i) {
case 0:
x = S.data[S.top[0]];
S.top[0]--;//下面的栈往下移
//x = S.data[S.top[0]--];
break;
case 1:
x = S.data[S.top[1]];
S.top[1]++;//上面的栈顶指针往上移
//x = S.data[S.top[1]++];
break;
}
return 1;
}
先进先出
队列的结构体定义及其基本操作。
#define MaxSize 50
typedef struct {
int data[MaxSize];//队列中存放数据类型为整型
int front, rear;//队首指针和队尾指针
}Queue;
void InitQueue(Queue& Q) {//初始化队列
Q.front = 0;
Q.rear = 0;
}
int IsEmpty(Queue Q) {//判断队列是否为空
if (Q.front == Q.rear)//若队首指针和队尾指针指向同一位置,则队列为空
return 1;
else
return 0;
}
队列的入队和出队
这里队尾指针指向元素的后一个位置,详见入队出队操作
入队争对的是队尾指针,需要判断队满
Q.rear == MaxSize
//顺序队列的入队和出队:
//这里队尾指针指向元素的后一个位置
int EnQueue(Queue& Q, int x) {//入队操作
if (Q.rear == MaxSize)//若队满,则无法入队
return 0;
Q.data[Q.rear] = x;//变量 x 入队
Q.rear++;//队尾指针后移
return 1;//入队成功
}
出队争对的是队头指针,需要判断队空
Q.front == Q.rear
int DeQueue(Queue& Q, int& x) {//出队操作
if (Q.front == Q.rear)//若队空,则无法出队
return 0;
x = Q.data[Q.front];//变量 x 接收出队元素
Q.front++;//队首指针后移
return 1;//出队成功
}
循环队列
由于之前Q.front == Q.rear判断队空,若循环,则既有判空,又有存满的意思,因此可以牺牲一个空间
,使得Q.front == Q.rear只能用来判空。
判空:Q.front == Q.rear
判满:(Q.rear + 1) % MaxSize == Q.front(rear向后移一个是front的话,说明满了)
队尾指针和队首指针往后移动的时候都需要+1取余
//循环队列的入队和出队:(牺牲一个存储空间)
int EnQueue(Queue& Q, int x) {//入队操作
if ((Q.rear + 1) % MaxSize == Q.front)//若队满,则无法入队
return 0;
Q.data[Q.rear] = x;//变量 x 入队
Q.rear = (Q.rear + 1) % MaxSize;//队尾指针后移
return 1;//入队成功
}
int DeQueue(Queue& Q, int& x) {//出队操作
if (Q.front == Q.rear)//若队空,则无法出队
return 0;
x = Q.data[Q.front];//变量 x 接收出队元素
Q.front = (Q.front + 1) % MaxSize;//队首指针后移
return 1;//出队成功
}
typedef struct {
int data[MaxSize];
int front, rear;
int tag;
}Queue;
void InitQueue(Queue& Q) {//初始化队列
Q.front = 0;
Q.rear = 0;
Q.tag = 0;
}
int EnQueue(Queue& Q, int x) {
if (Q.front == Q.rear && Q.tag == 1) {//若队满,则无法进行入队操作
return 0;
}
Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % MaxSize;//队尾指针后移
Q.tag = 1;//入队后可能会出现队满的情况,所以将 tag 标志域置为 1
return 1;
}
int DeQueue(Queue& Q, int& x) {
if (Q.front == Q.rear && Q.tag == 0) {
return 0;//队空
}
x = Q.data[Q.front];
Q.front = (Q.front + 1) % MaxSize;
Q.tag == 0;//出队后可能会出现队空的情况,所以将 tag 标志域置为 0
return 1;
}
//Q 是一个队列,S 是一个空栈,实现将队列中的元素逆置的算法。
void Reverse(Queue& Q, Stack& S) {
int x;
while (!IsEmpty(Q)) {//出队列入栈
DeQueue(Q, x);
Push(S, x);
}
while (!IsEmpty(S)) {//出栈入队列
Pop(S, x);
EnQueue(Q, x);
}
}