问题一:用两个栈实现一个队列
分析:队列遵循的是先进先出的原则,用两个栈来实现,一个栈管理入队列,另一个管理出队列,出队列就是将第一个栈的元素依次放入第二个栈中,然后在第二个栈进行出栈操作,所表现出的就是出队列了
typedef struct QueueS
{
Stack stack1;
Stack stack2;
} QueueS;
void QSInit(QueueS *pQS)
{
StackInit(&(pQS->stack1));
StackInit(&(pQS->stack2));
}
void QSPush(QueueS *pQS, StackDataType data)
{
// 对第一个栈进行压栈
StackPush(&(pQS->stack1), data);
}
void QSPop(QueueS *pQS)
{
Stack *p1 = &(pQS->stack1);
Stack *p2 = &(pQS->stack2);
// 如果栈 2 为空,从栈 1 将数据导过来
if (StackEmpty(p2)) {
// 把栈 1 的所有数据依次导入 栈 2
while (!StackEmpty(p1)) {
StackDataType data = StackTop(p1);
StackPush(p2, data);
StackPop(p1); //同时将栈 1 的元素出栈
}
}
//出队列
StackPop(p2);
}
StackDataType QSFront(QueueS *pQS)
{
Stack *p1 = &(pQS->stack1);
Stack *p2 = &(pQS->stack2);
if (StackEmpty(p2)) {
while (!StackEmpty(p1)) {
StackDataType data = StackTop(p1);
StackPush(p2, data);
StackPop(p1);
}
}
return StackTop(p2);
}
问题二:用两个队列实现一个栈
分析:栈遵循的是先进后出的原则
Push:往非空队列里插入(如果两个队列都是空,选第一个插入)
Pop:从非空队列中 move size - 1 个元素到 空队列中,pop 剩下的一个
Top: 从非空队列中 move size - 1 个元素到空队列中,返回剩下的一个的值, 把剩下的一个也放入另一个队列中
typedef struct {
Queue queue_1;
Queue queue_2;
} QStack;
// 初始化/销毁
void QSInit(QStack *pQS)
{
QueueInit(&(pQS->queue_1));
QueueInit(&(pQS->queue_2));
}
void QSDestroy(QStack *pQS)
{
QueueDestroy(&(pQS->queue_2));
QueueDestroy(&(pQS->queue_1));
}
// Push / Pop / Top
void QSPush(QStack *pQS, QDataType data)
{
//假设编程
//先假设 2 为空,看 1 是否为空
//如果 1 为空,那就给 1 入队列
Queue *pNotEmpty = &(pQS->queue_2);
if (QueueEmpty(pNotEmpty)) {
pNotEmpty = &(pQS->queue_1);
}
QueuePush(pNotEmpty, data);
}
void QSPop(QStack *pQS)
{
// 假设编程
// 我们程序正确的前提:
// 1. 一个空、一个非空
// 2. 两个都是空
Queue *pEmpty = &(pQS->queue_1);
Queue *pNotEmpty = &(pQS->queue_2);
if (QueueEmpty(pNotEmpty)) {
pEmpty = &(pQS->queue_2);
pNotEmpty = &(pQS->queue_1);
}
// 从非空队列中 move size - 1 个元素到 空队列中
while (QueueSize(pNotEmpty) > 1) {
QDataType data = QueueFront(pNotEmpty);
QueuePop(pNotEmpty);
QueuePush(pEmpty, data);
}
// pNotEmpty 队列里只剩一个数据
QueuePop(pNotEmpty);
}
QDataType QSTop(QStack *pQS)
{
// 假设编程
// 我们程序正确的前提:
// 1. 一个空、一个非空
// 2. 两个都是空
Queue *pEmpty = &(pQS->queue_1);
Queue *pNotEmpty = &(pQS->queue_2);
if (QueueEmpty(pNotEmpty)) {
pEmpty = &(pQS->queue_2);
pNotEmpty = &(pQS->queue_1);
}
// 从非空队列中 move size - 1 个元素到 空队列中
while (QueueSize(pNotEmpty) > 1) {
QDataType data = QueueFront(pNotEmpty);
QueuePop(pNotEmpty);
QueuePush(pEmpty, data);
}
// pNotEmpty 队列里只剩一个数据
QDataType r = QueueFront(pNotEmpty);
QueuePop(pNotEmpty);
QueuePush(pEmpty, r);
return r;
}
问题三:一个数组实现两个栈
分析:采用两边往中间生长的方式
扩容问题:当 top1>top2 时扩容
数据搬移问题
typedef struct {
int *array;
int top1;
int top2;
int capacity;
} TStack;
// 初始化
void TStackInit(TStack *pTS)
{
pTS->capacity = 10;
pTS->array = (int *)malloc(sizeof(int)* pTS->capacity);
pTS->top1 = 0;
pTS->top2 = pTS->capacity - 1; // 不要越界
}
void TStackDestroy(TStack *pTS)
{
free(pTS->array);
}
void ExpandIfRequired(TStack *pTS)
{
if (pTS->top1 <= pTS->top2) {
return;
}
int newCapacity = pTS->capacity * 2;
int *newArray = (int *)malloc(sizeof(int)* newCapacity);
assert(newArray);
// 搬移数据
// 搬移栈 1 的数据
for (int i = 0; i < pTS->top1; i++) {
newArray[i] = pTS->array[i];
}
// 搬移栈 2 的数据
// j ~ [top1, capacity) // 栈2 在老数组中所在下标区间
for (int j = pTS->top1; j < pTS->capacity; j++) {
// k 是新数组的下标
int k = j + pTS->capacity;
newArray[k] = pTS->array[j];
}
pTS->top2 += pTS->capacity;
pTS->capacity = newCapacity;
// 空间,下面两句的顺序不能交换
free(pTS->array);
pTS->array = newArray;
}
// Push
void Push_1(TStack *pTS, int data)
{
ExpandIfRequired(pTS);
pTS->array[pTS->top1] = data;
pTS->top1++;
}
void Push_2(TStack *pTS, int data)
{
ExpandIfRequired(pTS);
pTS->array[pTS->top2] = data;
pTS->top2--;
}
// Pop
void Pop_1(TStack *pTS)
{
pTS->top1--;
}
void Pop_2(TStack *pTS)
{
pTS->top2++;
}
// Top
int Top_1(TStack *pTS)
{
return pTS->array[pTS->top1 - 1];
}
int Top_2(TStack *pTS)
{
return pTS->array[pTS->top2 + 1];
}
// Size
int Size_1(TStack *pTS)
{
return pTS->top1;
}
int Size_2(TStack *pTS)
{
return pTS->capacity - pTS->top2 - 1;
}