在程序中引用的“seqstack.h”文件和“seqqueue.h”可以参见https://blog.csdn.net/Nessie_zhao/article/details/79917049
https://blog.csdn.net/Nessie_zhao/article/details/79834404
1.实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值)的时间复杂度为O(1);
思想:一次入栈两个元素,先入栈的是要存放的元素,后入栈的是栈中最小的元素
#include<stdio.h>
#include"seqstack.h"
typedef struct MinStack
{
SeqStack stack;
}MinStack;
void MinStackInit(MinStack* min_stack)
{
if(min_stack == NULL)
{
//非法输入
return;
}
SeqStackInit(&min_stack->stack);
}
void MinStackPush(MinStack* min_stack,SeqStackType value)
{
if(min_stack == NULL)
{
//非法输入
return;
}
SeqStackType min = value;
SeqStackType top;
int ret = SeqStackTop(&min_stack->stack,&top);
if(ret != 0)
{
//栈非空
min = top < value ? top : value;//如果top值比value值小就把top赋给min,否则把value值赋给min
}
//先插入value,再插入最小值,这样才能保证栈顶是最小值
SeqStackPush(&min_stack->stack,value);
SeqStackPush(&min_stack->stack,min);
return;
}
void MinStackPop(MinStack* min_stack)
{
if(min_stack == NULL)
{
//非法输入
return;
}
if(min_stack->stack.size == 0)//如果栈中没有元素
{
return;
}
//入栈的时候入了两个元素,所以出栈的时候也是两个两个一起出
SeqStackPop(&min_stack->stack);
SeqStackPop(&min_stack->stack);
return;
}
int MinStackTop(MinStack* min_stack,SeqStackType* value)
{
if(min_stack == NULL || value == NULL)
{
//非法输入
return 0;
}
if(min_stack->stack.size == 0){
return 0;
}
return SeqStackTop(&min_stack->stack,value);
}
//////////////////////////////////////////////////////////
//以下为测试代码
//////////////////////////////////////////////////////////
#if 1
#define TEST_HEADER printf("\n==========================%s=============================\n",__FUNCTION__);
void TestMinStack()
{
TEST_HEADER;
MinStack min_stack;
MinStackInit(&min_stack);
MinStackPush(&min_stack,'9');
MinStackPush(&min_stack,'5');
MinStackPush(&min_stack,'2');
MinStackPush(&min_stack,'7');
SeqStackType value;
int ret = MinStackTop(&min_stack,&value);
printf("ret expected : 1,actual %d\n",ret);
printf("value expected : 2,actual %c\n",value);
MinStackPop(&min_stack);
ret = MinStackTop(&min_stack,&value);
printf("ret expected : 1,actual %d\n",ret);
printf("value expected : 2,actual %c\n",value);
MinStackPop(&min_stack);
ret = MinStackTop(&min_stack,&value);
printf("ret expected : 1,actual %d\n",ret);
printf("value expected : 5 actual %c\n",value);
MinStackPop(&min_stack);
ret = MinStackTop(&min_stack,&value);
printf("ret expected : 1,actual %d\n",ret);
printf("value expected : 9,actual %c\n",value);
MinStackPop(&min_stack);
ret = MinStackTop(&min_stack,&value);
printf("ret expected : 0 actual %d\n",ret);
}
int main()
{
TestMinStack();
return 0;
}
#endif
2.使用两个栈实现一个队列;
思想:队列是先进先出,而栈是后进先出
定义一个input栈,一个output栈,入栈的时候将output中的元素都倒腾到input中,再压入想入栈的元素。出栈的时候将input中的元素都倒腾到output中,再出栈栈顶元素,就达到了队列的先进先出的效果。
#include <stdio.h>
#include"seqstack.h"
typedef struct QueueBy2Stack
{
//input 用于入队列场景
SeqStack input;
//output 用于出队列场景
SeqStack output;
}QueueBy2Stack;
void QueueBy2StackInit(QueueBy2Stack* q)
{
if(q == NULL)
{
//非法输入
return;
}
//将两个栈都初始化
SeqStackInit(&q->input);
SeqStackInit(&q->output);
}
void QueueBy2StackPush(QueueBy2Stack* q,SeqStackType value)
{
if(q == NULL)
{
//非法输入
return;
}
//先把output中的元素都倒腾到input中
while(1)
{
SeqStackType top;
int ret = SeqStackTop(&q->output,&top);
if(ret == 0)//栈中已经没有元素了
{
break;
}
//将output中的元素出栈,压入input中
SeqStackPop(&q->output);
SeqStackPush(&q->input,top);
}
//再把value入队列
SeqStackPush(&q->input,value);
return;
}
void QueueBy2StackPop(QueueBy2Stack* q)
{
if(q == NULL)
{
//非法输入
return;
}
//把input中的元素都倒腾到output中
while(1)
{
SeqStackType top;
int ret = SeqStackTop(&q->input,&top);
if(ret == 0)
{
break;
}
SeqStackPop(&q->input);
SeqStackPush(&q->output,top);
}
SeqStackPop(&q->output);
return;
}
int QueueBy2StackFront(QueueBy2Stack* q,SeqStackType* value)
{
if(q == NULL || value == NULL)
{
//非法输入
return 0;
}
while(1)
{
SeqStackType top;
int ret = SeqStackTop(&q->input,&top);
if(ret == 0)
{
break;
}
SeqStackPop(&q->input);
SeqStackPush(&q->output,top);
}
//现在output中栈顶元素就是最先进来的元素
return SeqStackTop(&q->output,value);
}
///////////////////////////////////////////////////////////
//以下为测试代码
///////////////////////////////////////////////////////////
#if 1
#define TEST_HEADER printf("\n===================================%s=====================================\n",__FUNCTION__);
void TestQueueBy2Stack()
{
TEST_HEADER;
QueueBy2Stack queue;
QueueBy2StackInit(&queue);
QueueBy2StackPush(&queue,'a');
QueueBy2StackPush(&queue,'b');
QueueBy2StackPush(&queue,'c');
QueueBy2StackPush(&queue,'d');
SeqStackType value;
int ret = QueueBy2StackFront(&queue,&value);
printf("ret :expected 1 ,actual %d\n",ret);
printf("value :expected a ,actual %c\n",value);
QueueBy2StackPop(&queue);
ret = QueueBy2StackFront(&queue,&value);
printf("ret :expected 1 ,actual %d\n",ret);
printf("value :expected b ,actual %c\n",value);
QueueBy2StackPop(&queue);
ret = QueueBy2StackFront(&queue,&value);
printf("ret :expected 1 ,actual %d\n",ret);
printf("value :expected c ,actual %c\n",value);
QueueBy2StackPop(&queue);
ret = QueueBy2StackFront(&queue,&value);
printf("ret :expected 1 ,actual %d\n",ret);
printf("value :expected d ,actual %c\n",value);
QueueBy2StackPop(&queue);
ret = QueueBy2StackFront(&queue,&value);
printf("ret :expected 0 ,actual %d\n",ret);
}
int main()
{
TestQueueBy2Stack();
return 0;
}
#endif
3.使用两个队列实现一个栈;
思想:两个队列哪个不为空就把要插入的元素插到那个队列中。有元素的定义为 from 队列,没有元素的定义为 to 队列,将 from 中的元素都倒腾到 to 中直至剩一个元素的时候再出队列,这样就达到了栈的后进先出的效果。
#include <stdio.h>
#include"seqqueue.h"
typedef struct StackBy2Queue
{
SeqQueue queue1;
SeqQueue queue2;
}StackBy2Queue;
void StackBy2QueueInit(StackBy2Queue* s)
{
if(s == NULL)
{
//非法输入
return;
}
//初始化两个队列
SeqQueueInit(&s->queue1);
SeqQueueInit(&s->queue2);
return;
}
void StackBy2QueuePush(StackBy2Queue* s,SeqQueueType value)
{
if(s == NULL)
{
//非法输入
return;
}
//取两个队列中非空的插入
SeqQueue* input = s->queue1.size != 0 ? &s->queue1 : &s->queue2;
SeqQueuePush(input,value);
return;
}
void StackBy2QueuePop(StackBy2Queue* s)
{
if(s == NULL)
{
//非法输入
return;
}
if(s->queue1.size == 0 && s->queue2.size == 0)
{
//说明是空栈
return;
}
//要把from中的元素倒腾到to中
//并且一直倒腾到from中只剩一个元素
SeqQueue* from = NULL;
SeqQueue* to = NULL;
//将有元素的队列赋给from
//没有元素的队列赋给to
if(s->queue1.size > 0)
{
from = &s->queue1;
to = &s->queue2;
}
else
{
from = &s->queue2;
to = &s->queue1;
}
while(1)
{
if(from->size == 1)
{
//from中只剩下一个元素
break;
}
SeqQueueType value;
SeqQueueFront(from,&value);
SeqQueuePop(from);
SeqQueuePush(to,value);
}
//from最后剩下的一个元素就是最后入队列的,最先出去
SeqQueuePop(from);
return;
}
int StackBy2QueueTop(StackBy2Queue* s,SeqQueueType* value)
{
if(s == NULL || value == NULL)
{
//非法输入
return 0;
}
//要把from中的元素倒腾到to中
//并且一直倒腾到from中只剩一个元素
SeqQueue* from = NULL;
SeqQueue* to = NULL;
if(s->queue1.size > 0)
{
from = &s->queue1;
to = &s->queue2;
}
else
{
from = &s->queue2;
to = &s->queue1;
}
while(1)
{
if(from->size == 0) {
//已经要停止倒腾了,此时的from的对首元素就是栈顶元素
break;
}
SeqQueueFront(from,value);
SeqQueuePop(from);
SeqQueuePush(to,*value);
}
SeqQueueFront(from,value);
}
///////////////////////////////////////////////////////////
//以下为测试代码
///////////////////////////////////////////////////////////
#if 1
#define TEST_HEADER printf("\n===================================%s======================================\n",__FUNCTION__);
void TestStackBy2Queue()
{
TEST_HEADER;
StackBy2Queue stack;
StackBy2QueueInit(&stack);
StackBy2QueuePush(&stack,'a');
StackBy2QueuePush(&stack,'b');
StackBy2QueuePush(&stack,'c');
StackBy2QueuePush(&stack,'d');
SeqQueueType value;
int ret = StackBy2QueueTop(&stack,&value);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected d,actual %c\n",value);
StackBy2QueuePop(&stack);
ret = StackBy2QueueTop(&stack,&value);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected c,actual %c\n",value);
StackBy2QueuePop(&stack);
ret = StackBy2QueueTop(&stack,&value);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected b,actual %c\n",value);
StackBy2QueuePop(&stack);
ret = StackBy2QueueTop(&stack,&value);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected a,actual %c\n",value);
StackBy2QueuePop(&stack);
ret = StackBy2QueueTop(&stack,&value);
printf("ret :expected 0,actual %d\n",ret);
}
int main()
{
TestStackBy2Queue();
return 0;
}
#endif
4.元素出栈、入栈顺序的合法性。如入栈的顺序(a,b,c,d,e),出栈序列为(d,e,c,,b,a);
思想:第一重循环,循环的遍历 input ,如果栈顶元素的值和 output_index 的值相等循环出栈,并且再次比较栈顶元素和output_index 移进后的值。
接下来比较栈顶元素和output_index所指向的元素是否相等
此时栈已经空了,而且output_index 也走到了结尾,所以该入栈顺序是合法的!按照此方法编写相应代码如下:
#include <stdio.h>
#include<stddef.h>
#include"seqstack.h"
//返回1表示能够变换成功
//返回0表示不能变换成功
int StackOrder(char input[],size_t input_size,char output[],size_t output_size)
{
SeqStack stack;
SeqStackInit(&stack);
//循环的把input的元素入栈
size_t i = 0;
size_t output_index = 0;
char top;
for(;i < input_size;++i)
{
SeqStackPush(&stack,input[i]);
int ret = SeqStackTop(&stack,&top);
if(ret == 0)
{
//栈已空,准备进行最终审判
break;
}
//取栈顶元素,和output_index指向的元素比较
while(1)
{
if(output_index >= output_size )
{
//output序列已经遍历完了,也得进行最终审判
break;
}
if(top != output[output_index])//比较栈顶元素和此时output_index所指的值是否相等,如果不相等就继续入栈
{
break;
}
++output_index;//output_index指针后移
SeqStackPop(&stack);//将栈顶元素出栈
}
}
while(1)
{
//如果不相等,继续循化取下一个input元素入栈
//如果相等
//a)移进output_index
//b) 把栈顶元素出栈
//c)循环的比较栈顶元素和output_index指向的元素的值
SeqStackTop(&stack,&top);
if(output_index >= output_size)
{
//output序列已经遍历完了,也得进行最终审判
break;
}
if(top != output[output_index])
{
break;
}
++output_index;
SeqStackPop(&stack);
}
//如果最终栈为空并且output_index指向output数组中的最后一个元素,就认为能够变换得到
//否则就无法变换得到
if(stack.size == 0 && output_index == output_size)
{
return 1;
}
return 0;
}
///////////////////////////////////////////////////////////
//以下为测试代码
///////////////////////////////////////////////////////////
#if 1
#define TEST_HEADER printf("\n======================================%s===================================\n",__FUNCTION__);
void TestStackOrder()
{
TEST_HEADER;
char input[5] = {'a','b','c','d','e'};
char output1[5] = {'d','e','c','b','a'};
char output2[5] = {'a','b','c','d','e'};
char output3[5] = {'e','d','c','b','a'};
char output4[5] = {'d','e','a','b','c'};
int size_in = sizeof(input);
int size_out1 = sizeof(output1);
int size_out2 = sizeof(output2);
int size_out3 = sizeof(output3);
int size_out4 = sizeof(output4);
int ret = StackOrder(input,size_in,output1,size_out1);
printf("ret : expected 1,actual %d\n",ret);
ret = StackOrder(input,size_in,output2,size_out2);
printf("ret : expected 1,actual %d\n",ret);
ret = StackOrder(input,size_in,output3,size_out3);
printf("ret : expected 1,actual %d\n",ret);
ret = StackOrder(input,size_in,output4,size_out4);
printf("ret : expected 0,actual %d\n",ret);
}
int main()
{
TestStackOrder();
return 0;
}
#endif
5.一个数组实现两个共享栈;
思想:
第一个栈:[0,top1)
第二个栈:[top2,max_size)
表示栈满了条件:top1 == top2
#include <stdio.h>
#define SharedStackMaxSize 1000
typedef char SharedStackType;
//[0,top1)表示第一个栈
//[top2,SharedStackMaxSize)表示第二个栈
typedef struct SharedStack
{
SharedStackType data[SharedStackMaxSize];
size_t top1;
size_t top2;
}SharedStack;
void SharedStackInit(SharedStack* s)
{
if(s == NULL)
{
//非法输入
return;
}
s->top1 = 0;//top1是从0开始,每入栈一个元素top1++
s->top2 = SharedStackMaxSize;//top2是从SharedStackMaxSize,每入栈一个元素,top2--
return;
}
void SharedStackPush1(SharedStack* s,SharedStackType value)
{
if(s == NULL)
{
//非法输入
return;
}
if(s->top1 >= s->top2)
{
//第一个栈已经满了
return;
}
//将value值赋给s->data[top1],并将top1后移
s->data[s->top1++] = value;
return;
}
void SharedStackPush2(SharedStack* s,SharedStackType value)
{
if(s == NULL)
{
//非法输入
return;
}
if(s->top1 >= s->top2)
{
//栈已经满了
return;
}
//先把top2前移,再将value值赋给s->data[top2]
s->data[--s->top2] = value;
return;
}
void SharedStackPop1(SharedStack* s)
{
if(s == NULL)
{
//非法输入
return;
}
if(s->top1 == 0)
{
return;
}
//直接将top1前移
--s->top1;
return;
}
void SharedStackPop2(SharedStack* s)
{
if(s == NULL)
{
//非法输入
return;
}
if(s->top2 == SharedStackMaxSize)
{
return;
}
//将top2后移
++s->top2;
return;
}
int SharedStackTop1(SharedStack* s,SharedStackType* value)
{
if(s == NULL || value == NULL)
{
//非法输入
return 0;
}
if(s->top1 == 0)
{
return 0;
}
//因为此时top1位置上没有元素,最后一个入栈的元素在top1-1位置上,所以需要先减1,再进行赋值
*value = s->data[s->top1 - 1];
return 1;
}
int SharedStackTop2(SharedStack* s,SharedStackType* value)
{
if(s == NULL || value == NULL)
{
//非法输入
return 0;
}
if(s->top2 == SharedStackMaxSize)
{
return 0;
}
//此时top2位置上就是最后入栈一个元素
*value = s->data[s->top2];
return 1;
}
///////////////////////////////////////////////////////////
//以下为测试代码
///////////////////////////////////////////////////////////
#define TEST_HEADER printf("\n=======================================%s=====================================\n",__FUNCTION__);
void TestSharedStack()
{
TEST_HEADER;
SharedStack stack;
SharedStackInit(&stack);
SharedStackPush1(&stack,'a');
SharedStackPush1(&stack,'b');
SharedStackPush1(&stack,'c');
SharedStackPush1(&stack,'d');
SharedStackType value1;
int ret = SharedStackTop1(&stack,&value1);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected d,actual %c\n",value1);
SharedStackPop1(&stack);
ret = SharedStackTop1(&stack,&value1);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected c,actual %c\n",value1);
SharedStackPop1(&stack);
ret = SharedStackTop1(&stack,&value1);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected b,actual %c\n",value1);
SharedStackPop1(&stack);
ret = SharedStackTop1(&stack,&value1);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected a,actual %c\n",value1);
SharedStackPop1(&stack);
ret = SharedStackTop1(&stack,&value1);
printf("ret :expected 0,actual %d\n",ret);
TEST_HEADER;
SharedStackPush2(&stack,'a');
SharedStackPush2(&stack,'b');
SharedStackPush2(&stack,'c');
SharedStackPush2(&stack,'d');
SharedStackType value2;
ret = SharedStackTop2(&stack,&value2);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected d,actual %c\n",value2);
SharedStackPop2(&stack);
ret = SharedStackTop2(&stack,&value2);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected c,actual %c\n",value2);
SharedStackPop2(&stack);
ret = SharedStackTop2(&stack,&value2);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected b,actual %c\n",value2);
SharedStackPop2(&stack);
ret = SharedStackTop2(&stack,&value2);
printf("ret :expected 1,actual %d\n",ret);
printf("value :expected a,actual %c\n",value2);
SharedStackPop2(&stack);
ret = SharedStackTop2(&stack,&value2);
printf("ret :expected 0,actual %d\n",ret);
}
int main()
{
TestSharedStack();
return 0;
}
#endif