1 栈只在一端(栈顶)进行运算,并非两端
栈是只允许在表的一端(栈顶)进行插入和删除操作的线性表;队列是只允许在表的一端(队尾)进行插入操作,在另一端(队头)进行删除操作的线性表。
所以栈只在一端(栈顶)进行运算,并非两端。
2 循环队列不是以链表指针的方式来实现头尾相接
循环队列的典型实现是基于数组的,通过对数组下标进行特定的运算(如取模)来实现队列的头尾相接,从而重复利用数组空间。
虽然从广义的 "指针" 概念(比如数组下标也可看作一种地址标识),但通常我们所说的用 "指针" 实现,更多是指像链表那样用指针变量来链接节点。
而循环队列一般不用这种链表指针的方式来实现头尾相接,所以这一说法错误,答案选 "×"。
3 队列只允许在一端(队尾)进行插入(增加)操作,在另一端(队头)进行删除(减少)操作
队列是一种 "先进先出"(FIFO)的线性表,只允许在一端(队尾)进行插入(增加)操作,在另一端(队头)进行删除(减少)操作,并非下端和上端既能增加又能减少。
4 当有 n 个元素依次进栈时,合法的出栈序列数目恰好是第 n 个卡特兰数。

5 在单链表表示的链式队列里,队头位于链表的链头位置
队列是 "先进先出" 的线性结构,链式队列中,队头元素是最先进入队列的,在单链表表示的链式队列里,**队头位于链表的链头位置,这样出队(删除队头元素)操作可以直接从链头进行,方便高效;**而队尾位于链尾,用于入队操作。所以用单链表表示的链式队列的队头在链表的链头位置。
6 只有尾指针的循环链队列的入队和出队

以下是用 C 语言实现只有尾指针的循环链队列的入队和出队操作:
cpp
#include <stdio.h>
#include <stdlib.h>
// 定义队列节点结构
typedef struct Node {
int data;
struct Node *next;
} Node;
// 入队操作
void enQueue(Node **rear, int value) {
// 创建新节点
Node *newNode = (Node *)malloc(sizeof(Node));
if (newNode == NULL) {
printf("内存分配失败\n");
exit(1);
}
newNode->data = value;
// 如果队列为空
if (*rear == NULL) {
*rear = newNode;
newNode->next = newNode; // 自己指向自己,形成循环
} else {
// 新节点的 next 指向原队头(尾指针的 next 指向队头)
newNode->next = (*rear)->next;
// 尾节点的 next 指向新节点
(*rear)->next = newNode;
// 尾指针后移到新节点
*rear = newNode;
}
}
// 出队操作
int deQueue(Node **rear) {
// 队列为空的情况
if (*rear == NULL) {
printf("队列为空,无法出队\n");
exit(1);
}
Node *front = (*rear)->next; // 队头节点
int data = front->data;
// 如果队列中只有一个节点
if (front == *rear) {
*rear = NULL;
} else {
// 尾指针的 next 指向原队头的下一个节点,即新的队头
(*rear)->next = front->next;
}
free(front);
return data;
}
// 测试函数
int main() {
Node *rear = NULL;
// 入队
enQueue(&rear, 1);
enQueue(&rear, 2);
enQueue(&rear, 3);
// 出队并打印
printf("出队元素: %d\n", deQueue(&rear));
printf("出队元素: %d\n", deQueue(&rear));
printf("出队元素: %d\n", deQueue(&rear));
// 再次入队测试
enQueue(&rear, 4);
printf("出队元素: %d\n", deQueue(&rear));
return 0;
}
代码说明
- 入队操作(
enQueue
) :- 首先创建新节点存储要入队的数据。
- 如果队列为空(尾指针
rear
为NULL
),则新节点的next
指向自身,尾指针指向新节点,形成只有一个节点的循环队列。 - 如果队列不为空,新节点的
next
指向原队头(尾指针的next
指向队头),然后尾节点的next
指向新节点,最后尾指针后移到新节点。
- 出队操作(
deQueue
) :- 先判断队列是否为空,为空则无法出队。
- 找到队头节点(尾指针的
next
指向队头),保存队头节点的数据。 - 如果队列中只有一个节点,出队后队列为空,尾指针置为
NULL
。 - 否则,尾指针的
next
指向原队头的下一个节点(即新的队头),然后释放原队头节点的内存,返回其数据。
- 测试部分 :在
main
函数中进行入队和出队操作的测试,验证代码的正确性。
7 实现两个共享存储区、栈顶相向增长的顺序栈的入栈和出栈

1. 定义栈结构
cpp
#define maxsize 100 // 假设最大容量为 100
typedef struct {
int data[maxsize]; // 共享的存储数组
int top1; // 栈 S1 的栈顶指针,初始为 -1
int top2; // 栈 S2 的栈顶指针,初始为 maxsize
} DoubleStack;
2. 入栈操作
cpp
// 入栈操作,stack 为双栈,x 为入栈元素,stackNum 为栈编号(1 表示 S1,2 表示 S2)
int push(DoubleStack *stack, int x, int stackNum) {
// 检查是否栈满(两个栈顶指针相邻,说明空间用尽)
if (stack->top1 + 1 == stack->top2) {
printf("栈满,无法入栈\n");
return 0;
}
if (stackNum == 1) {
// S1 入栈,栈顶指针上移,元素放入对应位置
stack->data[++(stack->top1)] = x;
} else if (stackNum == 2) {
// S2 入栈,栈顶指针下移,元素放入对应位置
stack->data[--(stack->top2)] = x;
} else {
printf("栈编号错误\n");
return 0;
}
return 1;
}
3. 出栈操作
cpp
// 出栈操作,stack 为双栈,x 用于存储出栈元素,stackNum 为栈编号(1 表示 S1,2 表示 S2)
int pop(DoubleStack *stack, int *x, int stackNum) {
if (stackNum == 1) {
// 检查 S1 是否为空
if (stack->top1 == -1) {
printf("S1 栈空,无法出栈\n");
return 0;
}
// S1 出栈,栈顶指针下移,取出元素
*x = stack->data[stack->top1--];
} else if (stackNum == 2) {
// 检查 S2 是否为空
if (stack->top2 == maxsize) {
printf("S2 栈空,无法出栈\n");
return 0;
}
// S2 出栈,栈顶指针上移,取出元素
*x = stack->data[stack->top2++];
} else {
printf("栈编号错误\n");
return 0;
}
return 1;
}
简单解释
- 入栈 :两个栈
S1
和S2
栈顶相向,S1
栈顶从存储区起始位置(top1
初始为 -1)向上增长,S2
栈顶从存储区末尾位置(top2
初始为maxsize
)向下增长。入栈时先判断是否栈满(top1 + 1 == top2
表示空间用尽),若不满则根据栈编号,调整对应栈顶指针并放入元素。 - 出栈:出栈时先判断对应栈是否为空,若不为空则根据栈编号,调整对应栈顶指针并取出元素。