工欲善其事,必先利其器,先温习一下基础。
1、什么是栈:
栈,存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算机领域里,就是指数据暂时存储的地方,所以才有进栈、出栈的说法。
2、栈的特点:
栈的特点是先进后出,进出元素都是在同一端(栈顶)。
2.1 入栈
2.2出栈
我们可以把栈的操作想象成蒸包子的过程,在没有放包子时最上面的那层和最下面那层都是处在同一层,这也就是栈空的特点;当需要蒸包子时,总会把它一层一层的堆起来,而最先放上去的总会再最后才能被拿下来,并且每次都只能往最上面那层放;同样往下取的时候也是只能从最上层取。
综上可以知道栈是先入后出,且只能对栈顶操作。
3、队列
就像我们排队买东西时,先去排的先买到。(了解是先入先出的特点就行)
4、用栈实现队列操作
栈是先入后出而队列是先入先出,显然要实现一个队列至少要两个栈。
-
将数据全部存储完后再全部取出
由上图可见将一组数据经过入栈出栈两次后就实现了一个队列
2. 多次存储与多次取出
上面虽然已经实现了一个队列,但并不能像队列那样能存储多个数据而仅读取少量数据。
设想一下,加入我存了几个数据后想读取部分,后再存储数据再全部读取出来,上面的方法已然难以实现,而要实现它仅仅需要加上一点注意事项罢了。
那么问题来了,我们后面再读取数据的时候如果再按之前的路子来,读到的将会是5而不是2,这样就像有人插队那样不礼貌了。
那么如果我们设置这样一个条件就可以解决:在每次需要读取数据的时候优先判断栈2内是不是还有数据没有读完,如果有就直接读栈二内的数据,如果没有的话就一次把栈1内所有数据出栈到栈2中,然后再读数据。 嗯~ 很有效
5、代码实现
先贴上封装好的入栈出栈子函数
/*
* 功能:向栈内加入数据
* 参数:
* @1:栈的地址
* @2:入栈数据
* 返回值:成功返回OK,失败返回原因
*/
int enterStack(Stack *pStack,data_type item)
{
if(NULL == pStack)
return NULL_ERROR;
//判断是否栈满
if(pStack->top == N-1)
return FULL;
//入栈
pStack->top++;
pStack->arr[pStack->top] = item;
return OK;
}
/*
* 功能:出栈
* 参数:
* @1:栈的地址
* @2:出栈的数据
* 返回值:成功返回OK,失败返回原因
*/
int outStack(Stack *pStack,data_type *item)
{
if(NULL == pStack)
return NULL_ERROR;
//判断是否栈空
if(pStack->top == -1)
return EMPTY;
//出栈
*item = pStack->arr[pStack->top];
pStack->top--;
return OK;
}
5.1 一次性的存储与读取
int main()
{
//待操作数据
data_type data[5] = {1,2,3,4,5};
data_type temp = 0;
//创建第一个栈
Stack *first = create();
//创建第二个栈
Stack *second = create();
int i = 0;
//先将数据全部入栈1
while(OK == enterStack(first, data[i++]));
//将栈1内所有数据出栈到栈2
while(OK == outStack(first, &temp))
{
if(OK != enterStack(second, temp))
{
break;
}
}
//最后将栈2内所有数据出栈并打印看结果
while(OK == outStack(second, &temp))
{
printf("%d ",temp);
}
puts("");
return 0;
}
结果如下:
完全符合队列的先入先出
5.2 多次或单次操作
数据的存储还是没变,但是读取改了个子函数
/*
* 功能:出队
* 参数:
* @1:第一个栈的地址
* @2:第二个栈的地址
* @3:出栈的数据被存储地址
* 返回值:成功返回OK,失败返回原因
*/
int outQueue(Stack *first,Stack *second,data_type *item)
{
if(NULL == first || NULL == second)
return NULL_ERROR;
data_type temp = 0;
//判断第二个栈是否为空
if(-1 == second->top)
{
//第二个栈空时把第一个栈内所有存储数据导入第二个栈
while(1)
{
if(outStack(first,&temp) != OK)
break;
if(enterStack(second,temp) != OK)
break;
}
}
if(outStack(second,item) != OK)
return ERROR;
return OK;
}
主函数实现
int main()
{
data_type item = 0;
int op = 0;
Stack *first = create();
Stack *second = create();
while(1)
{
menu();
scanf("%d",&op);
if(0 == op)
break;
switch(op)
{
case 1:
printf("请输入要入队的数据:\n");
scanf("%d",&item);
if(OK != enterStack(first,item))
{
printf("入队失败\n");
}
break;
case 2:
if(outQueue(first,second,&item) != OK)
{
printf("出队失败\n");
break;
}
printf("出队数据为:%d\n",item);
break;
case 3:
destroy(&first);
destroy(&second);
break;
}
}
return 0;
}
以上若出现问题欢迎各位大佬指出。