栈与队列
栈Stack
栈的结构体定义及基本操作。
#define MaxSize 50
typedef struct {int data[MaxSize];//栈中存放数据类型为整型int top;//栈顶指针
}Stack;
void InitStack(Stack& S) {//初始化栈S.top = -1;
}
int IsEmpty(Stack S) {//判断栈是否为空if (S.top == -1)return 1;elsereturn 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;
}
int GetTop(Stack S, int& x) {//读取栈顶元素if (S.top == -1)//若栈空则无栈顶元素return 0;x = S.data[S.top];return 1;
}
有一个带头结点的单链表 L,结点结构由 data 和 next 两个域构成,其中data 域为字符型。试设计算法判断该链表的全部 n 个字符是否中心对称。例如xyx、xyyx 都是中心对称。
- 结点个数为偶数时,正常处理,个数为奇数时,最中间元素不将其压栈处理,
int central_symmetry(LinkList L) {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->next;}while (p != NULL) {//右半边字符与栈顶元素比较if (p->data == S[i]) {i--;p = p->next;}else {return 0;//非中心对称}}return 1;
}
假设一个算术表达式中包含小括号和中括号 2 种类型的括号,编写一个算法来判别表达式中的括号是否配对,假设算术表达式存放于字符数组中,以字符‘\0’作为算术表达式的结束符。
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;}
}
两个栈 S1、S2 都采用顺序栈方式,并共享一个存储区[0,…,MaxSize-1],为了尽量利用空间,减少溢出的可能,可采用栈顶相向、迎面增长的存储方式。试设计写出此栈的定义和 S1、S2 有关入栈和出栈的操作算法。
#define MaxSize 50
typedef struct{int data[MaxSize];int top[2];//一个top[0],一个top[1]指针
}DStack;
初始化
void InitDStack(DStack& S) {S.top[0] = -1;S.top[1] = MaxSize;
}
入栈
int push(int i, int x) {if (i < 0 || i>1) {return 0;}if (S.top[1] - S.top[0] == 1) {return 0;}switch (i) {case 0:S.top[0]++;S.data[S.top[0]] = x;//S.data[++S.top[0]] = x;break;case 1: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;
}
队列Queue
队列的结构体定义及其基本操作。
#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;elsereturn 0;
}
队列的入队和出队
这里队尾指针指向元素的后一个位置,详见入队出队操作
//顺序队列的入队和出队:
//这里队尾指针指向元素的后一个位置
int EnQueue(Queue& Q, int x) {//入队操作if (Q.rear == MaxSize)//若队满,则无法入队return 0;Q.data[Q.rear] = x;//变量 x 入队Q.rear++;//队尾指针后移return 1;//入队成功
}
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.rear + 1) % MaxSize == Q.front(rear向后移一个是front的话,说明满了)
//循环队列的入队和出队:(牺牲一个存储空间)
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;//出队成功
}
若希望循环队列中的元素都能得到利用,则需设置一个标志域 tag,并以tag的值为0或1来区分队头指针front和队尾指针rear相同时的队列状态是“空”还是“满”。试编写与此结构相应的入队和出队算法。
typedef struct {int data[MaxSize];int front, rear;int tag;
}Queue;
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 标志域置为 1return 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 标志域置为 0return 1;
}
Q 是一个队列,S 是一个空栈,实现将队列中的元素逆置的算法。
//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);}
}