我们在来看今天的代码之前,相信大家以前可能都封装过栈和队列的基本操作,所以我们在用到一些栈和队列的基本操作的时候,只需要把栈和队列的头文件引进来就可以调用它的一些基本操作的函数,就不用再把那些函数再写一遍了,但在调用栈和队列的头文件的时候,我们必须把栈和队列的头文件和源文件复制到当前这个项目工程底下,不然调不过来。
那我也把栈和队列的那些基本函数给大家放在这吧,便于理解。
Stack.h
#ifndef __STACK_H__
#define __STACK_H__
#include<stdio.h>
#include<assert.h>
#define MaxSize 10
typedef int SDataType;
typedef struct Stack
{
SDataType _arry[MaxSize];
int top;//size
}Stack;
void StackInit(Stack* ps);
void StackPush(Stack* ps, SDataType data);
void StackPop(Stack* ps);
int StackSize(Stack* ps);
int StackEmpty(Stack* ps);
void Print(Stack* ps);
SDataType StackTop(Stack* ps);
#endif //__STACK_H__
Stack.c
#include "Stack.h"
void StackInit(Stack* ps)
{
assert(ps != NULL);
ps->top = 0;
}
void Print(Stack* ps)
{
assert(ps != NULL);
while (ps->top--)
{
printf("%d ", ps->_arry[ps->top]);
}
printf("\n");
}
void StackPush(Stack* ps, SDataType data)
{
assert(ps != NULL);
if (ps->top == MaxSize)
return;
else
{
ps->_arry[ps->top] = data;
ps->top++;
}
}
void StackPop(Stack* ps)
{
assert(ps != NULL);
if (ps->top)
ps->top--;
}
int StackSize(Stack* ps)
{
assert(ps != NULL);
return ps->top;
}
int StackEmpty(Stack* ps)
{
assert(ps != NULL);
if (0 == ps->top)
return 1;
else
return 0;
}
SDataType StackTop(Stack* ps)
{
assert(ps != NULL);
return ps->_arry[ps->top - 1];
}
Queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include<stdio.h>
#include<assert.h>
#include<malloc.h>
typedef int QDataType;
typedef struct QListNode
{
QDataType data;
struct QListNode* next;
}QListNode;
typedef struct Queue
{
struct QListNode* Front;
struct QListNode* Back;
}Queue;
void QueueInit(Queue* q);
void QueuePush(Queue* q, QDataType data);
void QueuePop(Queue* q);
QDataType QueueFront(Queue* q);
QDataType QueueBack(Queue* q);
int QueueSize(Queue* q);
int QueueIsEmpty(Queue* q);
QListNode* BuyQListNode(QDataType data);
void PrintQueue(Queue* q);
#endif //__QUEUE_H__
Queue.c
#include"Queue.h"
void QueueInit(Queue* q)
{
assert(q);
QListNode* p = (QListNode*)malloc(sizeof(QListNode));
if (NULL == p)
{
printf("创建结点失败\n");
return;
}
else
{
p->data = 0;
p->next = NULL;
}
q->Back = q->Front = p;
}
void PrintQueue(Queue* q)
{
assert(q);
QListNode* cur = q->Front;
while (cur)
{
printf("%d--->", cur->data);
cur = cur->next;
}
printf("OVER\n");
}
void QueuePush(Queue* q, QDataType data)
{
assert(q);
QListNode* NewNode = BuyQListNode(data);
q->Back->next = NewNode;
q->Back = NewNode;
}
void QueuePop(Queue* q)
{
assert(q);
QListNode* Del;
if (q->Back != q->Front)//说明队中有元素,可以删除
{
Del = q->Front->next;
q->Front->next = Del->next;
if (q->Front->next == q->Back)
{
q->Back = q->Front;
free(Del);
q->Front->next = NULL;
}
else
{
free(Del);
}
}
}
QDataType QueueFront(Queue* q)
{
assert(q);
return q->Front->next->data;
}
QDataType QueueBack(Queue* q)
{
assert(q);
return q->Back->data;
}
int QueueSize(Queue* q)
{
assert(q);
int count = 0;
QListNode* cur = q->Front;
while (cur)
{
count++;
cur = cur->next;
}
return count;
}
int QueueIsEmpty(Queue* q)
{
{
assert(q);
if (q->Back == q->Front)//队为空,返回1
return 1;
return 0;
}
}
QListNode* BuyQListNode(QDataType data)
{
QListNode* NewNode = (QListNode*)malloc(sizeof(QListNode));
if (NULL == NewNode)
{
printf("创建结点失败!\n");
return;
}
NewNode->data = data;
NewNode->next = NULL;
return NewNode;
}
1.实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值)的时间复杂度为O(1)
分析:时间复杂度为O(1),那就是要求我们一次就能找到它的最小值。那我们可以定义两个栈,一个栈专门用来保存它的最小值,等需要的时候我们把保存最小值的这个栈栈顶元素出栈就行。那我们如何让保存最小值的栈的栈顶元素始终是最小值呢,我们就要每次都通过比较更新它的栈顶元素,在第一次的时候,我们让第一个数据同时入两个栈,第二次的时候,我们先让它入数据栈,然后再让第二次入栈的元素与min栈中栈顶元素比较,如果<=min栈的栈顶元素,我们就让它也入min栈,如果大于,则只入到数据栈中,继续取第三个元素,这样min栈的栈顶元素始终都是当前最小的那个值。
具体代码如下:
MinStack.h
#ifndef __STACKTOMIN_H__
#define __STACKTOMIN_H__
#define MaxSize 10
#include<stdio.h>
#include<assert.h>
#include "Stack.h"
typedef struct MinStack
{
Stack _data;
Stack _min;
}MinStack;
void MinStackInit(MinStack* s);
void MinStackPush(MinStack* s, SDataType data);
void MinStackPop(MinStack* s);
SDataType MinStackTop(MinStack* s);
SDataType MinStackMin(MinStack* s);
int MainSatckSize(MinStack* s);
int IsEmpty(MinStack* s);
#endif //__STACKTOMIN_H__
MinStack.c
#include"MinStack.h"
void MinStackInit(MinStack* s)
{
assert(s);
StackInit(&s->_data);
StackInit(&s->_min);
}
void MinStackPush(MinStack* s, SDataType data)
{
assert(s);
StackPush(&s->_data, data);
if (StackEmpty(&s->_min))//如果min栈为空,说明压入的是第一个元素,把第一个元素也压入min栈中
{
StackPush(&s->_min, data);
}
else//用压入的数据和min栈栈顶元素比较,若data<min栈顶元素,data压入min栈
{
if (data <= StackTop(&s->_min))
{
StackPush(&s->_min, data);
}
}
}
void MinStackPop(MinStack* s)
{
assert(s);
if (StackTop(&s->_data) == StackTop(&s->_min))
{
StackPop(&s->_data);
StackPop(&s->_min);
}
StackPop(&s->_data);
}
SDataType MinStackTop(MinStack* s)
{
assert(s);
return StackTop(&s->_data);
}
SDataType MinStackMin(MinStack* s)
{
assert(s);
return StackTop(&s->_min);
}
int MainSatckSize(MinStack* s)
{
return StackSize(&s->_data);
}
int IsEmpty(MinStack* s)
{
return StackEmpty(&s->_data);
}
test.c
#include"MinStack.h"
int main()
{
MinStack s;
MinStackInit(&s);
MinStackPush(&s, 1);
MinStackPush(&s, 2);
MinStackPush(&s, 3);
MinStackPush(&s, 4);
printf("top = %d\n", MinStackTop(&s));
printf("size = %d\n", MainSatckSize(&s));
printf("min = %d\n", MinStackMin(&s));
MinStackPop(&s);
MinStackPush(&s, 0);
MinStackPush(&s, 4);
printf("top = %d\n", MinStackTop(&s));
printf("size = %d\n", MainSatckSize(&s));
printf("min = %d\n", MinStackMin(&s));
return 0;
}
运行结果正确:
2.使用两个栈实现一个队列
分析:
在把元素从一个栈导入另一个栈的时候,我们每次要把这个栈的栈顶元素入到另一个栈去,然后这个栈的栈顶元素出栈,依次进行,直到这个栈为空,我们就把这个栈的元素完全导入到另一个栈中了。
我们来看看具体代码实现
QueueBy2Stack.h
#ifndef __QUEUEBY2STACK_H__
#define __QUEUEBY2STACK_H__
#include<stdio.h>
#include<assert.h>
#include"Stack.h"
#define MaxSize 10
typedef struct Queue
{
Stack s1;
Stack s2;
}Queue;
void QueueBy2StackPush(Queue* q, SDataType data);
void QueueBy2StackPop(Queue* q);
SDataType QueueBy2StackTop(Queue* q);
SDataType QueueBy2StackBack(Queue* q);
int QueueBy2StackSize(Queue* q);
int IsQueueBy2StackEmpty(Queue* q);
#endif //__QUEUEBY2STACK_H__
QueueBy2Stack.c
#include"QueueBy2Stack.h"
void InitQueueBy2Stack(Queue* q)
{
assert(q);
StackInit(&q->s1);
StackInit(&q->s2);
}
void QueueBy2StackPush(Queue* q, SDataType data)
{
assert(q);
StackPush(&q->s1, data);
}
void QueueBy2StackPop(Queue* q)
{
assert(q);
if (!StackEmpty(&q->s2))
{
StackPop(&q->s2);
}
else
{
while (!StackEmpty(&q->s1))
{
StackPush(&q->s2, StackTop(&q->s1));
StackPop(&q->s1);
}
StackPop(&q->s2);
}
}
SDataType QueueBy2StackTop(Queue* q)
{
assert(q);
if (!StackEmpty(&q->s2))
{
return StackTop(&q->s2);
}
else
{
while (!StackEmpty(&q->s1))
{
StackPush(&q->s2, StackTop(&q->s1));
StackPop(&q->s1);
}
return StackTop(&q->s2);
}
}
SDataType QueueBy2StackBack(Queue* q)
{
assert(q);
if (!StackEmpty(&q->s1))
{
return StackTop(&q->s1);
}
else
{
while (!StackEmpty(&q->s2))
{
StackPush(&q->s1, StackTop(&q->s2));
StackPop(&q->s2);
}
return StackTop(&q->s1);
}
}
int QueueBy2StackSize(Queue* q)
{
assert(q);
return StackSize(&q->s1) + StackSize(&q->s2);
}
int IsQueueBy2StackEmpty(Queue* q)
{
assert(q);
return StackEmpty(&q->s1) && StackEmpty(&q->s2);//1---是空
}
test.c
#include"QueueBy2Stack.h"
int main()
{
Queue q;
InitQueueBy2Stack(&q);
QueueBy2StackPush(&q, 1);
QueueBy2StackPush(&q, 2);
QueueBy2StackPush(&q, 3);
printf("Size = %d\n", QueueBy2StackSize(&q));
printf("Front = %d\n", QueueBy2StackTop(&q));
printf("Back = %d\n", QueueBy2StackBack(&q));
QueueBy2StackPop(&q);
printf("Size = %d\n", QueueBy2StackSize(&q));
printf("Front = %d\n", QueueBy2StackTop(&q));
printf("Back = %d\n", QueueBy2StackBack(&q));
QueueBy2StackPush(&q, 4);
QueueBy2StackPush(&q, 5);
printf("Size = %d\n", QueueBy2StackSize(&q));
printf("Front = %d\n", QueueBy2StackTop(&q));
printf("Back = %d\n", QueueBy2StackBack(&q));
return 0;
}
运行结果正确:
3.使用两个队列实现一个栈
分析:
我们来看看具体代码实现吧:
StackBy2Queue.h
#ifndef __STACKBY2QUEUE_H__
#define __STACKBY2QUEUE_H__
#include"Queue.h"
typedef struct StackBy2Queue
{
Queue q1;
Queue q2;
}StackBy2Queue;
void StackBy2QueueInit(StackBy2Queue* q);
void StackBy2QueuePush(StackBy2Queue* q, QDataType data);
void StackBy2QueuePop(StackBy2Queue* q);
QDataType StackBy2QueueTop(StackBy2Queue* q);
int StackBy2QueueSize(StackBy2Queue* q);
int StackBy2QueueEmpty(StackBy2Queue* q);
#endif //__STACKBY2QUEUE_H__
StackBy2Queue.c
#include"StackBy2Queue.h"
void StackBy2QueueInit(StackBy2Queue* q)
{
assert(q);
QueueInit(&q->q1);
QueueInit(&q->q2);
}
void StackBy2QueuePush(StackBy2Queue* q, QDataType data)
{
assert(q);
if (!QueueIsEmpty(&q->q1))//队1中有数据
{
QueuePush(&q->q1, data);
}
else//队2中有数据或两个队都为空
{
QueuePush(&q->q2, data);
}
}
void StackBy2QueuePop(StackBy2Queue* q)
{
assert(q);
if (!QueueIsEmpty(&q->q1))//队1中有数据
{
while (QueueSize(&q->q1)>2)//因为带有头结点,是所以是>2
{
QueuePush(&q->q2, QueueFront(&q->q1));
QueuePop(&q->q1);
}
QueuePop(&q->q1);
}
else
{
while (QueueSize(&q->q2)>2)//因为带有头结点,是所以是>2
{
QueuePush(&q->q1, QueueFront(&q->q2));
QueuePop(&q->q2);
}
QueuePop(&q->q2);
}
}
QDataType StackBy2QueueTop(StackBy2Queue* q)
{
assert(q);
if (!QueueIsEmpty(&q->q1))
{
return QueueBack(&q->q1);
}
else
{
return QueueBack(&q->q2);
}
}
int StackBy2QueueSize(StackBy2Queue* q)
{
assert(q);
return QueueSize(&q->q1) + QueueSize(&q->q2) - 1;
}
int StackBy2QueueEmpty(StackBy2Queue* q)
{
if (2 == QueueSize(&q->q1) + (QueueSize(&q->q2)))
{
return 1;
}
else
{
return 0;
}
}
运行结果正确:
4.元素出栈入栈顺序的合法性。如入栈的序列(1,2,3,4,5),出栈序列为(4,5,3,2,1)
分析:
我们来看看具体代码实现:
IsStackValidOrder.h
#ifndef __ISSTACKVALIDORDER_H__
#define __ISSTACKVALIDORDER_H__
#include"Stack.h"
int IsStackValidOrder(int* InArr, int InSize, int* OutArr, int OutSize);
#endif //__ISSTACKVALIDORDER_H__
IsStackValidOrder.c
#include"IsStackValidOrder.h"
int IsStackValidOrder(int* InArr, int InSize, int* OutArr, int OutSize)
{
int inIdx = 0;
int outIdx = 0;
Stack s;
StackInit(&s);
if (OutSize != InSize)
{
return 0;
}
while (outIdx < OutSize)
{
if (inIdx>=InSize)
{
return;
}
else
{
while (StackEmpty(&s) || OutArr[outIdx] != StackTop(&s))
{
StackPush(&s, InArr[inIdx++]);
}
StackPop(&s);
outIdx++;
}
}
return 1;
}
test.c
#include"IsStackValidOrder.h"
int main()
{
int InArr[] = { 1, 2, 3, 4, 5 };
int OutArr[] = { 4, 5, 3, 1, 2 };
int ret = 0;
ret = IsStackValidOrder(InArr, 5, OutArr, 5);
if (1 == ret)
{
printf("匹配成功\n");
}
else
{
printf("匹配失败\n");
}
return 0;
}
运行结果正确:
5.一个数组实现两个栈(共享栈)。
分析:
具体代码:
SharedStack.h
#ifndef __SHAREDSTACK_H__
#define __SHAREDSTACK_H__
#include<stdio.h>
#include<assert.h>
typedef int SDataType;
#define MaxSize 10
typedef struct SharedStack
{
SDataType arry[MaxSize];
int top1;
int top2;
}SharedStack;
void SharedStackInit(SharedStack* ps);
void SharedStackPush(SharedStack* ps, SDataType data, int which);
void SharedStackPop(SharedStack* ps, int which);
int SharedStackSize(SharedStack* ps);
#endif //__SHAREDSTACK_H__
SharedStack.c
#include"SharedStack.h"
void SharedStackInit(SharedStack* ps)
{
assert(ps);
int i = 0;
for (i = 0; i < MaxSize; i++)
{
ps->arry[i] = 0;
}
ps->top1 = 0;
ps->top2 = MaxSize - 1;
}
void SharedStackPush(SharedStack* ps, SDataType data, int which)
{
assert(ps);
if (ps->top1 > ps->top2)
{
return;
}
else
{
if (1 == which)
{
ps->arry[ps->top1++] = data;
}
else
{
ps->arry[ps->top2--] = data;
}
}
}
void SharedStackPop(SharedStack* ps, int which)
{
assert(ps);
if (0 == ps->top1 && ps->top2 == MaxSize - 1)//如果栈里没有元素,不要出栈
{
return;
}
else
{
if (1 == which)
{
ps->top1--;
}
else
{
ps->top2++;
}
}
}
test.c
#include"SharedStack.h"
int main()
{
SharedStack s;
SharedStackInit(&s);
SharedStackPush(&s, 1, 1);
SharedStackPush(&s, 2, 1);
SharedStackPush(&s, 6, 2);
SharedStackPush(&s, 7, 2);
SharedStackPop(&s, 2);
return 0;
}
运行结果:
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。