第一部分、两个队列实现一个栈
本来想画图,可实在没这时间,且理解起来相对容易
主要思想是,先将 所有数先导入一个队列A中去,另一个队列B此刻为空。将队列A中除了最后一个数其他都导入B中,然后将A中仅剩的一个数输出,这样循环下去,就造成了栈的假象。
实现如下:
//队列实现
#ifndef QUEUE_H
#define QUEUE_H
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct NODE
{
int n;
struct NODE *pnext;
}nod, * pnod;
typedef struct S
{
pnod phead;
pnod ptail;
}ss, * pss;
void init(pss);
void en_queue(pss,int );
void out_queue(pss,int &);
bool is_empty(pss);
int nodes_remain(pss);
void init(pss Y)
{
Y->phead=(pnod)malloc(sizeof(nod));
if(Y->phead == NULL)
exit(-1);
Y->phead->pnext=NULL;
Y->ptail=Y->phead;
}
void en_queue(pss Y,int val)
{
pnod new_x=(pnod)malloc(sizeof(nod));
if(new_x == NULL)
exit(-1);
new_x->n=val;
new_x->pnext=NULL;
Y->ptail->pnext=new_x;
Y->ptail=new_x;
}
bool is_empty(pss Y)
{
if(Y->phead == Y->ptail)
return true;
else
return false;
}
void out_queue(pss Y,int & T)
{
if(is_empty(Y))
return;
else
{
pnod r=Y->phead->pnext;
Y->phead->pnext=r->pnext;
if(Y->phead->pnext==NULL) //我就觉得这里需要注意一下 就是只剩下一个没有val的头结点和一个尾节点指向的节点的时候 没有这一步的话无法判断 is_empty
Y->ptail=Y->phead;
T = r->n;
free(r);
}
}
int nodes_remain(pss Y)
{
int count=0;
pnod p = Y->phead->pnext;
while(p)
{
count++;
p = p->pnext;
}
return count;
}
#endif
//main
#include <stdio.h> //与两个栈实现一个队列相对应
#include "queue.h"
int main()
{
int a[] = {1,2,3,4,5,6,7};
pss Queue_A,Queue_B;
Queue_A = (pss)malloc(sizeof(ss));
Queue_B = (pss)malloc(sizeof(ss));
init(Queue_A);
init(Queue_B);
int i;
for(i=0;i<7;i++)
en_queue(Queue_A,a[i]);
printf("Datas stored in Queue_A:\n"); //输出存储在A中的数据
for(i=0;i<7;i++)
printf("%d%c",a[i],(i+1)%7==0?'\n':' ');
int temp;
//以下为按照栈的形式输出第一个数
for(i=0;i<6;i++) //将队列A中数据逐个导入B中,但是 最后一个数不导 而是直接输出out_queue 这样就把最后一个数第一个输出了
{
out_queue(Queue_A,temp);
en_queue(Queue_B,temp);
}
printf("Output the first data as Stack-style : \n");
out_queue(Queue_A,temp);
printf("%d\n",temp);
//以上是输出一个数 那如果要连续输出呢
//以下就是连续输出 为了避免只将一个栈作为存储 而另一个作为临时的浪费 利用两个指针
pss p, q;
if(is_empty(Queue_A))
{
p = Queue_B;
q = Queue_A;
}
else
{
p = Queue_A;
q = Queue_B;
}
while(!is_empty(p)) //将p作为有数的那个栈 q作为空栈
{
while(nodes_remain(p)>1) //使队列中仅剩一个数
{
out_queue(p,temp);
en_queue(q,temp);
}
out_queue(p,temp);
printf("%d ",temp);
if(is_empty(Queue_A)) //有数的队列已经变成了另一个 此刻将p指针指向这个队列
{
p = Queue_B;
q = Queue_A;
}
else
{
p = Queue_A;
q = Queue_B;
}
}
puts("");
return 0;
}
第二部分:两个栈实现一个队列
简单的设想是将所有元素导入A,再倒入B,之后直接输出。这里考虑了如果需要新增元素该怎么处理,并不需要因为新元素来回倒腾
//栈实现
#ifndef STACK_H
#define STACK_H
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
typedef struct subject
{
int data;
struct subject *pnext;
}node,* pnode;
typedef struct First
{
pnode ptop;
pnode pbottom;
}s,* ps;
void init(ps S)
{
S->ptop=(pnode)malloc(sizeof(node));
if(NULL == S->ptop)
{
printf("FALE\n");
exit(1);
}
S->ptop->pnext=NULL;
S->pbottom=S->ptop;
}
void push(ps S,int val)
{
pnode newx=(pnode)malloc(sizeof(node));
if(NULL == newx)
{
printf("FALE\n");
exit(1);
}
newx->data=val;
newx->pnext=S->ptop;
S->ptop=newx;
}
bool empty(ps S)
{
if(S->ptop==S->pbottom)
return true;
else
return false;
}
void pop(ps S,int &e)
{
if(empty(S))
return;
else
{
pnode r;
r=S->ptop;
S->ptop=r->pnext;
e = r->data;
free(r);
}
}
void traverse(ps S)
{
if(empty(S))
return;
else
{
pnode p;
p=S->ptop;
while(p!=S->pbottom)
{
printf("%d ",p->data);
p=p->pnext;
}
putchar('\n');
}
}
void clear(ps S)
{
pnode p;
pnode q;
p=S->ptop;
while(p != S->pbottom)
{
q=p->pnext;
free(p);
p=q;
}
S->ptop=S->pbottom;
}
#endif
//main
#include <stdio.h> //实现 出队列操作
#include <malloc.h>
#include "stack.h"
//不难理解 只是在看到问题时候是否想得到是否有思路 将两个栈一起来实现队列的出队
int main()
{
ps Stack_A = (ps)malloc(sizeof(s));
ps Stack_B = (ps)malloc(sizeof(s));
init(Stack_A);
init(Stack_B);
int i;
int a[] = {1,2};
printf("The origin order of the array:\n");
for(i=0;i<2;i++)
printf("%d ",a[i]);
puts("");
for(i=0;i<2;i++)
push(Stack_A,a[i]);
printf("Datas in Stack_A:\n");
traverse(Stack_A);
int temp;
while(!empty(Stack_A)) //此处可以优化 可以计数 不必将所有都导入B 而是留下A中的最后一个 继而直接输出 而不是导入B后由B输出
{
pop(Stack_A,temp);
push(Stack_B,temp);
}
printf("Datas in Stack_B:\n");
traverse(Stack_B);
pop(Stack_B,temp);
printf("Output the first number as the Queue-style :\n");
printf("%d\n",temp);
//以上实现的是一次性 若是需要反复加入新元素同时能够按队列形式输出呢
//一种方式是在按需输出元素后,将所有元素导入A如果需要入队则直接入A 之后再入B,输出,按需重复上述步骤
//还有一种方式如下:
//如果需要入队 则直接进A (为什么不需要来回倒腾一番呢?因为我要入队的数全都暂时存在A中 一旦B中的数消耗掉了 就将A中的数字导入B)
push(Stack_A,10); //不空的话 说明数全在A中 直接将此数入A
//这种方式如果要出队 并不会在上一次出队后将B中所有数全倒回A 而是将计就计(当然 这得需要没有新增的入队操作)
if(empty(Stack_B)) //如果为空,即B中元素全都输出完了,则将A中的后来元素全部导入B
while(!empty(Stack_A))
{
pop(Stack_A,temp);
push(Stack_B,temp);
}
printf("Datas in Stack_B:\n");
traverse(Stack_B);
pop(Stack_B,temp); //如果不空 则说明数全在B中(或者说并没有进行入队操作) 则直接将B中数据pop
printf("Output the next number as the Queue-style :\n");
printf("%d\n",temp);
//当然 如果要继续的话 可以设循环
return 0;
}