这个算法,根据理解个人认为两个栈实现队列最主要考察的应该是用链栈来实现,感觉如果是链栈来实现对于节点的处理会稍微麻烦一些吧。不然的话并不难,就是数组下标的处理罢了,但对于下标处理也和A还是需要考虑得仔细些,不然也有很多问题。
先说说这个算法的思路,我能想到的让时间复杂度比较优化的方法就2个吧:
1.栈1负责入队,然后,出队的时候,把栈1除栈底的外倒入栈2,然后令栈1底为空,然后,要入队的时候再把栈2的倒回栈1,这样节省的时间就是如果时连续出队的话,只用继续把栈2的顶弹出即可,但如果是一只交替的进出就不怎么好了。于是,我的办法就是另外一种。
2.大概就是栈1只负责入队,栈2只负责出队即可,基本上不用倒入,需要倒入的情况只有第一次出队和当栈2为空时(栈2为空即无法出队),入队时就直接入栈1,出队时判断栈2是否为空,如果不为空则出队,否则为空,就把栈1的全部倒入栈2,这样对于频繁的进出操作会节省时间一些。
下面是我的代码(改天有空再把它改成函数版的):
#include <stdio.h> #include <stdlib.h> #include <conio.h> #define N 10 int main(void) { int stack1[N], stack2[N]; int i, j, k; ///i记录栈1,j记录栈2 char c; i = j = 0; puts("1) 进队 2) 出队"); puts("3) 队首 4) 队尾"); puts("5) 队列 6) 队员个数"); puts("7) 退出"); while((c = getch()) != '7') { switch(c) { case '1' : printf(" 进队:"); if(i < N) scanf("%d", &stack1[i++]); else printf("Queue overflow! "); break; case '2' : printf(" 出队 "); if(j == 0 && i != 0) ///栈2为空时,将栈1除底外的倒入栈2 { for(j = 0; j < i - 1; j++) { stack2[j] = stack1[i - 1 - j]; } i = 0; } else if(j > 0) ///栈2不为空,则出队只用花O(1)的时间 { j--; } else { printf("Queue overflow! "); } break; case '3' : if(j != 0) printf(" 队首元素:%d ", stack2[j - 1]); else if(j == 0 && i + j != 0) printf(" 队首元素:%d ", stack1[0]); else printf("Queue is Empty! "); break; case '4' : if(i != 0) printf(" 队尾元素:%d ", stack1[i - 1]); else if(i == 0 && i + j != 0) printf(" 队尾元素:%d ", stack2[0]); else printf("Queue is Empty! "); break; case '5' : printf(" 显示数据: "); if(i + j != 0) { if(j == 0) ///如果栈2为空,则只需显示栈1的 { for(k = 0; k < i; k++) printf("%d ", stack1[k]); } else ///否则栈2不为空 { for(k = j - 1; k >= 0; k--) printf("%d ", stack2[k]); if(i > 0) { for(k = 0;k < i; k++) printf("%d ", stack1[k]); } } } else printf("Queue is Empty! "); break; case '6' : printf(" 当前队员个数为: %d ", i + j); break; } } return 0; }
函数版(并且发现之前的有点小BUG,也一并修改了):
/** * 两个栈实现一个队列 * */ #include <stdio.h> #include <stdlib.h> #include <conio.h> #define N 10 struct Stack{ int val; int top1; int top2; }stack1[N], stack2[N]; /** 函数定义 */ struct Stack* initQueue(); void PushQueue(); void PopQueue(); void GetQueueFirst(); void GetQueueLast(); void PrintQueue(); /** 操作函数 */ struct Stack* initQueue(void) { struct Stack *p; p = (struct Stack*)malloc(sizeof(struct Stack)); p->top1 = p->top2 = 0; return p; } void PushQueue(struct Stack *p, int X) { if(p->top1 < N) stack1[p->top1++].val = X; else printf("Queue overflow! "); } void PopQueue(struct Stack *p) { if(p->top2 == 0 && p->top1 != 0) ///栈2为空时,将栈1的倒入栈2 { for(p->top2 = 0; p->top2 < p->top1 - 1; p->top2++) { stack2[p->top2] = stack1[p->top1 - 1 - p->top2]; } p->top1 = 0; } else if(p->top2 > 0) ///栈2不为空,则出队只用花O(1)的时间 { p->top2--; } else { printf("Queue overflow! "); } } void GetQueueFirst(struct Stack *p) { if(p->top2 != 0) printf("%d ", stack2[p->top2 - 1].val); else if(p->top2 == 0 && p->top1 + p->top2 != 0) printf("%d ", stack1[0].val); else printf("Queue is Empty! "); } void GetQueueLast(struct Stack *p) { if(p->top1 != 0) printf("%d ", stack1[p->top1 - 1].val); else if(p->top1 == 0 && p->top1 + p->top2 != 0) printf("%d ", stack2[0].val); else printf("Queue is Empty! "); } void PrintQueue(struct Stack *p) { int k; if(p->top1 + p->top2 != 0) { if(p->top2 == 0) ///如果栈2为空,则只需显示栈1的 { for(k = 0; k < p->top1; k++) printf("%d ", stack1[k].val); } else ///否则栈2不为空 { for(k = p->top2 - 1; k >= 0; k--) printf("%d ", stack2[k]); if(p->top1 > 0) { for(k = 0;k < p->top1; k++) printf("%d ", stack1[k].val); } } } else printf("Queue is Empty! "); } /** 测试 */ int main(void) { struct Stack *p; int X; char c; puts("1) 进队 2) 出队"); puts("3) 队首 4) 队尾"); puts("5) 队列 6) 队员个数"); puts("7) 退出"); p = initQueue(); while((c = getch()) != '7') { switch(c) { case '1' : printf(" 进队:"); scanf("%d", &X); PushQueue(p, X); break; case '2' : printf(" 出队 "); PopQueue(p); break; case '3' : printf(" 队首元素:"); GetQueueFirst(p); break; case '4' : printf(" 队尾元素:"); GetQueueLast(p); break; case '5' : printf(" 显示数据: "); PrintQueue(p); break; case '6' : printf(" 当前队员个数为: %d ", p->top1 + p->top2); break; } } free(p); p = NULL; return 0; }