一、实现一个栈,要求实现Push、Pop、MIn的时间复杂度为O(1)
1)对于栈来说,Push、Pop的时间复杂度本来就为O(1);
2)但返回最小值的时间复杂度则会上升到O(N);因为需要从头遍历
解决方法1:在每一次出入栈的同时,就将最小值存起来。用两个数(入栈值、最小值)表示一个整体;
(注意)此时,Top栈顶元素实际上为第二个元素的值。
typedef struct MinStack {
Stack stack;
} MinStack;
SDatatype MinStackTop(MinStack *pMS)
{
return StackNextTop(&(pMS->stack));
}
SDatatype MinStackMin(MinStack *pMS)
{
return StackTop(&(pMS->stack));
}
void MinStackInit(MinStack *pMS)
{
assert(pMS);
StackInit(&pMS->stack);
}
//主要方面,压栈过程与出栈过程
void MinStackPush(MinStack *pMS,SDatatype data)
{
SDatatype min;
if (!StackIsEmpty(&pMS->stack) && StackTop(&pMS->stack) < data) {
min = StackTop(&pMS->stack);
StackPush(&pMS->stack, data);
StackPush(&pMS->stack, min);
}
else {
StackPush(&pMS->stack, data);
StackPush(&pMS->stack, data);
}
}
void MinStackPop(MinStack *pMS)
{
StackPop(&pMS->stack);
StackPop(&pMS->stack);
}
void MinStackDestory(MinStack *pMS)
{
assert(pMS);
StackDestory(&pMS->stack);
}
解决方法2:用两个栈实现一个栈,其中一个栈里存最小值,另外一个栈里存数据;1栈nomal 2栈min
(注意)入栈时:1栈正常入,2栈先判断,再决定入2栈
出栈时:先判断1栈和2栈的元素;若相同,则同时出1、2栈
typedef struct MinStack2 {
Stack nomal;
Stack min;
} MinStack2;
void MinStack2Init(MinStack2 *pMS)
{
assert(pMS);
StackInit(&pMS->nomal);
StackInit(&pMS->min);
}
SDatatype MinStack2Top(MinStack2 *pMS)
{
return StackTop(&pMS->nomal);
}
SDatatype MinStack2Min(MinStack2 *pMS)
{
return StackTop(&pMS->min);
}
void MinStack2Destory(MinStack2 *pMS)
{
StackDestory(&pMS->min);
StackDestory(&pMS->nomal);
}
//主要方面,函数出入栈的实现
void MinStack2Push(MinStack2 *pMS,SDatatype data)
{
assert(pMS);
StackPush(&pMS->nomal, data);
//注意先比较,再确定要不要将值入栈到最小栈里
if (StackIsEmpty(&pMS->min) || MinStack2Min(pMS) >= data) {
StackPush(&pMS->min, data);
}
}
void MinStack2Pop(MinStack2 *pMS)
{
assert(pMS);
//出栈时注意:若最小栈和正常栈的数据不同,只出正常栈即可。
if (MinStack2Min(pMS) == MinStack2Top(pMS)) {
StackPop(&pMS->min);
}
StackPop(&pMS->nomal);
}
二、使用两个栈实现一个队列
1)这个问题涉及到数据在两个栈之间的转移:想要Pop,就必须要先移动数据;想要Top,必须要先移动数据;
2)这个问题的基础是先将stack1的数据清空。
typedef struct QueueBy2Stack {
Stack stack1;
Stack stack2;
} QueueBy2Stack;
void QueueBy2StackInit(QueueBy2Stack *pQ)
{
StackInit(&pQ->stack1);
StackInit(&pQ->stack2);
}
void QueueBy2StackDestory(QueueBy2Stack *pQ)
{
StackDestory(&pQ->stack1);
StackDestory(&pQ->stack2);
}
//正常的入栈到stack1;
void QueueBy2StackPush(QueueBy2Stack *pQ,SDatatype data)
{
StackPush(&pQ->stack1, data);
}
//将stack1的数据清空;
//如果stack2中仍有数据,则什么都不做;
void QueueBy2StackMove(QueueBy2Stack *pQ)
{
SDatatype data;
if (StackIsEmpty(&pQ->stack2)) {
while (!StackIsEmpty(&pQ->stack1)) {
data = StackTop(&pQ->stack1);
StackPush(&pQ->stack2, data);
StackPop(&pQ->stack1);
}
}
}
//先移动stack1中的数据-->stack2中,在stack2中进行Pop
void QueueBy2StackPop(QueueBy2Stack *pQ)
{
QueueBy2StackMove(pQ);
assert(!StackIsEmpty(&pQ->stack2));
StackPop(&pQ->stack2);
}
//先移动stack中的数据-->stack2中,在stack2中进行Top
SDatatype QueueBy2StackTop(QueueBy2Stack *pQ)
{
QueueBy2StackMove(pQ);
assert(!StackIsEmpty(&pQ->stack2));
StackTop(&pQ->stack2);
}
void TestQueueBy2Stack()
{
QueueBy2Stack queue;
QueueBy2StackInit(&queue);
QueueBy2StackPush(&queue, 1);
QueueBy2StackPush(&queue, 2);
QueueBy2StackPush(&queue, 3);
QueueBy2StackPush(&queue, 4);
QueueBy2StackPush(&queue, 5);
printf("%d\n", QueueBy2StackTop(&queue));
QueueBy2StackPop(&queue);
printf("%d\n", QueueBy2StackTop(&queue));
QueueBy2StackPop(&queue);
printf("%d\n", QueueBy2StackTop(&queue));
QueueBy2StackPop(&queue);
printf("%d\n", QueueBy2StackTop(&queue));
QueueBy2StackPop(&queue);
printf("%d\n", QueueBy2StackTop(&queue));
QueueBy2StackPop(&queue);
QueueBy2StackDestory(&queue);
}
三、使用两个队列实现一个栈
1)实际上也是利用两个队列之间来回转移数据,实现栈的基本功能。
2)Push:直接往非空队列里面插入;
3)Pop:先确定空队列和非空队列;再将非空队列中的数据转移到空队列;剩余最后一个数据(QueueSize>1)时,直接Pop;
4)Top:先确定空队列和非空队列;再将非空队列中的数据转移到空队列;剩余最后一个数据(QueueSize>1)时,将最后一个数据取出来存着,再将其放入空队列中;return 存着的;
typedef struct StackBy2Queue {
Queue queue1;
Queue queue2;
} StackBy2Queue;
void StackBy2QueueInit(StackBy2Queue *pS)
{
QueueInit(&pS->queue1);
QueueInit(&pS->queue2);
}
void StackBy2QueueDestory(StackBy2Queue *pS)
{
QueueDestory(&pS->queue1);
QueueDestory(&pS->queue2);
}
//先确定空队列和非空队列;再Push进非空队列;
void StackBy2QueuePush(StackBy2Queue *pQ,QDatatype data)
{
Queue *NotEmpty = &pQ->queue1;
Queue *Empty = &pQ->queue2;
if (!QueueIsEmpty(Empty)) {
NotEmpty = &pQ->queue2;
Empty = &pQ->queue1;
}
QueuePush(NotEmpty, data);
}
//先确定空队列和非空队列;再将非空队列中的数据转移到空队列;
//最后,当剩余最后一个数据时(QueueSize>1),将其Pop出去;
void StackBy2QueuePop(StackBy2Queue *pQ)
{
QDatatype data;
Queue *NotEmpty = &pQ->queue1;
Queue *Empty = &pQ->queue2;
if (!QueueIsEmpty(Empty)) {
NotEmpty = &pQ->queue2;
Empty = &pQ->queue1;
}
while (QueueSize(NotEmpty) > 1) {
data = QueueFront(NotEmpty);
QueuePop(NotEmpty);
QueuePush(Empty, data);
}
QueuePop(NotEmpty);
}
//先确定空队列和非空队列;再将非空队列中的数据转移到空队列;
//当剩余最后一个数据时(QueueSize>1),将其保存起来,然后将其再放入空队列中;
//最后,直接返回return 保存的数据;
QDatatype StackBy2QueueFront(StackBy2Queue *pQ)
{
QDatatype data;
Queue *NotEmpty = &pQ->queue1;
Queue *Empty = &pQ->queue2;
if (!QueueIsEmpty(Empty)) {
NotEmpty = &pQ->queue2;
Empty = &pQ->queue1;
}
while (QueueSize(NotEmpty) > 1) {
data = QueueFront(NotEmpty);
QueuePop(NotEmpty);
QueuePush(Empty, data);
}
data = QueueFront(NotEmpty);
QueuePop(NotEmpty);
QueuePush(Empty, data);
return data;
}
void TestStackBy2Queue()
{
StackBy2Queue stack;
StackBy2QueueInit(&stack);
StackBy2QueuePush(&stack, 1);
StackBy2QueuePush(&stack, 2);
StackBy2QueuePush(&stack, 3);
StackBy2QueuePush(&stack, 4);
printf("%d\n", StackBy2QueueFront(&stack));
StackBy2QueuePop(&stack);
printf("%d\n", StackBy2QueueFront(&stack));
StackBy2QueuePop(&stack);
printf("%d\n", StackBy2QueueFront(&stack));
StackBy2QueuePop(&stack);
printf("%d\n", StackBy2QueueFront(&stack));
StackBy2QueuePop(&stack);
StackBy2QueueDestory(&stack);
}
四、一个数组实现两个栈(共享栈)
#define CAPACITY (4)
typedef int DataType;
typedef struct ShareStack {
DataType *array;
int capacity;
int top1;
int top2;
} ShareStack;
void ShareStackInit(ShareStack *pS)
{
assert(pS);
pS->array = (DataType *)malloc(sizeof(DataType)* CAPACITY);
pS->capacity = CAPACITY;
pS->top1 = 0;
pS->top2 = pS->capacity - 1;
}
void ShareStackDestory(ShareStack *pS)
{
assert(pS);
free(pS->array);
pS->array = NULL;//防止野指针的出现
pS->capacity = 0;
pS->top1 = 0;
pS->top2 = 0;
}
void ExpendIfRequired(ShareStack *pS)
{
assert(pS);
if (pS->top1 - 1 != pS->top2) {
return;
}
int oldcapacity = pS->capacity;
pS->capacity *= 2;
DataType *NewArray = (DataType *)malloc(sizeof(DataType)* pS->capacity);
memset(NewArray, 0x00, sizeof(DataType)*pS->capacity);
int Stack2Size = oldcapacity - 1 - pS->top2;
memcpy(NewArray, pS->array, sizeof(DataType)*pS->top1);
memcpy(NewArray + pS->capacity - Stack2Size, pS->array + pS->top2, sizeof(DataType)*Stack2Size);
pS->top2 = pS->capacity - 1 - Stack2Size;
free(pS->array);
pS->array = NewArray;
}
void ShareStackPush(ShareStack *pS, int which, DataType data)
{
assert(pS);
ExpendIfRequired(pS);
if (which == 1) {
pS->array[pS->top1++] = data;
}
if (which == 2) {
pS->array[pS->top2--] = data;
}
}
void ShareStackPop(ShareStack *pS, int which)
{
assert(pS);
if (which == 1) {
assert(pS->top1 > 0);
pS->top1--;
}
if (which == 2) {
assert(pS->top2 < pS->capacity - 1);
pS->top2++;
}
}
DataType ShareStackTop(ShareStack *pS, int which)
{
assert(pS);
if (which == 1) {
assert(pS->top1 > 0);
return pS->array[pS->top1 - 1];
}
if (which == 2) {
assert(pS->top2 < pS->capacity - 1);
return pS->array[pS->top2 + 1];
}
}
void TestShareStack()
{
ShareStack stack;
ShareStackInit(&stack);
int i = 0;
ShareStackPush(&stack, 1, 1);
ShareStackPush(&stack, 1, 2);
ShareStackPush(&stack, 1, 3);
ShareStackPush(&stack, 2, 4);
ShareStackPush(&stack, 2, 5);
ShareStackPush(&stack, 2, 16);
ShareStackPush(&stack, 2, 17);
for (i = 0; i < 3; i++) {
printf("%d\n", ShareStackTop(&stack, 1));
ShareStackPop(&stack, 1);
}
for (i = 0; i < 4; i++) {
printf("%d\n", ShareStackTop(&stack, 2));
ShareStackPop(&stack, 2);
}
ShareStackDestory(&stack);
}