栈和队列的相关面试题
2017-10-16 22:25
211 查看
问题一:实现一个栈,要求实现push(出栈),pop(出栈),Min(返回栈中最小值的操作)的时间复杂度为0(1).
解题思路:
直接说核心的思想就是,做一个辅助栈,用来储存入栈元素中的最小值,当你实现Min返回栈中最小的元素的时候,直接从辅助栈中弹出元素,如果主栈栈顶和辅助栈的栈顶元素大小一样,同时将主栈栈顶的元素也弹出。
代码实现如下(C语言):
问题二:用两个栈实现一个队列。
解题思路:已知队列的特性是先进先出而栈的特性是先进后出,所以需要做的就是颠倒两个栈中的元素,从而实现队列的特性。
代码实现如下(C语言)
问题三:使用两个队列实现一个栈
解题思路:这一题和第二题的整体思路是一致的就是利用队列的特性将其中的元素进行灵活的变化从而实现栈的特性。
代码实现如下(C语言):
问题四:元素出栈,入栈顺序的合法性。例如入栈序列(1,2,3,4,5),出栈序列(4,5,3,2,1)判断这个出栈顺序是否合法
解题思路:设置一个辅助栈,将入栈顺序中的元素依次按其入栈的顺序压入,注意,在压入的过程中和出栈序列中的元素出栈顺序依次从前往后比较,如果压入的元素等于出栈序列的前排元素则将其弹出,然后出栈序列指向下一个元素,继续比较一次栈顶是否相等,不相等则继续进行压栈。循环循环判断,最后当所以元素都进行压栈操作后栈不为空则非法,如果为空则合法。
代码如下(C语言实现)
1.入栈12345 出栈 45321
2.入栈12345 出栈45312
问题五:一个数组实现两个栈(栈共享)
解题思路:
这有三种实现方式:
1.奇偶栈,将数组下标为0当作第一个栈的栈低,下标为1当作第二个栈的栈低,将数组偶数位下标的看作第一个栈的储存空间,奇数位看作第二个栈的储存空间。
2.将数组的中间看作两个栈的栈低,入栈时分别向左右入栈,当任何一边满栈时就进行扩容
3.将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。
因为方法1和方法2都会浪费空间,利用率较低,所以我们只实现第三种栈
代码实现如下(C语言)
解题思路:
直接说核心的思想就是,做一个辅助栈,用来储存入栈元素中的最小值,当你实现Min返回栈中最小的元素的时候,直接从辅助栈中弹出元素,如果主栈栈顶和辅助栈的栈顶元素大小一样,同时将主栈栈顶的元素也弹出。
代码实现如下(C语言):
#include<stdio.h> #include<stdlib.h> #include<malloc.h> #define MAX 10 #define ADD 10 typedef int Datatype; typedef struct stack { Datatype *base; Datatype *top; int capacity; }stack,*stackptr; void Iintsytack(stackptr s)//初始化栈 { s->base = (Datatype *)malloc(sizeof(Datatype)*MAX);//申请空间 if (NULL == s->base) { exit(0); } else { s->top = s->base; s->capacity = MAX; } } void Capacityif(stackptr s)//判满函数 { if (MAX == s->top - s->base)//判断是否栈满,如果满则扩容 { s->base = (Datatype *)realloc(s->base, sizeof(Datatype)*(s->capacity + ADD)); if (NULL == s->base) { exit(0); } s->top = s->base + s->capacity; s->capacity += ADD; } } void pushstack(stackptr s, stackptr s1, Datatype e) { Capacityif(s); Capacityif(s1); if (s1->base == s1->top)//如果辅助栈为空则压入 { *(s1->top++) = e; } if (e < *(s1->top - 1))//如果小于辅助栈压入 { *(s1->top++) = e; } *(s->top++) = e;//主栈正常入栈 } void popstack(stackptr s, stackptr s1, Datatype *e)//弹栈 { if (s->base == s->top) { exit(0); } *e = *(--s->top); if (*e == *(s1->top - 1))//如果相等则辅助栈出栈 { s1->top--; } } void Minelem(stackptr s1, Datatype *e) { if (s1->base == s1->top) { exit(0); } *e = *(--s1->top); } int main()//main()函数中为测试代码 { stack stackn;//定义主栈 stack stackmin;//定义辅助栈 int min; Iintsytack(&stackn); Iintsytack(&stackmin); pushstack(&stackn, &stackmin, 1); pushstack(&stackn, &stackmin, 5); pushstack(&stackn, &stackmin, 6); pushstack(&stackn, &stackmin, 3); pushstack(&stackn, &stackmin, 0); pushstack(&stackn, &stackmin, 2); Minelem(&stackmin, &min); printf("栈中最小元素=%d\n", min); system("pause"); return 0; }
问题二:用两个栈实现一个队列。
解题思路:已知队列的特性是先进先出而栈的特性是先进后出,所以需要做的就是颠倒两个栈中的元素,从而实现队列的特性。
代码实现如下(C语言)
#include<stdio.h> #include<stdlib.h> #include<malloc.h> #define MAX 10 #define ADD 10 typedef int Datatype; typedef struct stack { Datatype *base; Datatype *top; int capacity; }stack,*stackptr; void Iintsytack(stackptr s)//初始化栈 { s->base = (Datatype *)malloc(sizeof(Datatype)*MAX);//申请空间 if (NULL == s->base) { exit(0); } else { s->top = s->base; s->capacity = MAX; } } void Capacityif(stackptr s)//判满函数 { if (MAX == s->top - s->base)//判断是否栈满,如果满则扩容 { s->base = (Datatype *)realloc(s->base, sizeof(Datatype)*(s->capacity + ADD)); if (NULL == s->base) { exit(0); } s->top = s->base + s->capacity; s->capacity += ADD; } } void pushstack(stackptr s, stackptr s1, Datatype *arr,int len)//队列形成的函数 { Capacityif(s);//如果栈满则扩容 while (len--)//入栈A { *(s->top++) = *arr++; } while (s->top != s->base)//入栈B { *(s1->top++) = *(--s->top); } } void popstack(stackptr s1, Datatype *e)//弹栈 { if (s1->top == s1->base) { return; } *e = *(--s1->top); } int Getsize(stackptr s1) { return s1->top - s1->base; } int main()//main()函数中为测试代码 { int e; int arr[5] = { 1, 2, 3, 4, 5 }; int len = sizeof(arr) / sizeof(*arr); stack stacka;//定义栈A stack stackb;//定义栈B Iintsytack(&stacka); Iintsytack(&stackb); pushstack(&stacka, &stackb, arr,len); for (int i = 0; i < len; i++) { popstack(&stackb, &e); printf("%d ", e); } system("pause"); return 0; }
问题三:使用两个队列实现一个栈
解题思路:这一题和第二题的整体思路是一致的就是利用队列的特性将其中的元素进行灵活的变化从而实现栈的特性。
代码实现如下(C语言):
#include<stdio.h> #include<malloc.h> #include<stdlib.h> #include<math.h> #define MAX 10 typedef int Datatype; typedef struct circleQ { Datatype *data; int front; int rear; }circleQ, *circleQptr; void InitcircleQ(circleQptr s)//初始化队列 { s->data = (Datatype *)malloc(sizeof(Datatype)*MAX);//申请空间 if (s->data == NULL) return; else { s->front = 0; s->rear = 0; } } void Pushelem(circleQptr s, Datatype *arr,int len) { if ((s->rear + 1) % MAX == s->front)//判断队列是否满了 { return; } while (len--)//首先入A队列 { s->data[s->rear] = *arr++; s->rear = (s->rear + 1) % MAX; } } int Getcount(circleQptr s)//或者 { return (int)fabs(s->front - s->rear); } void Popelem(circleQptr s, circleQptr s1, Datatype *e)//弹出元素 { if ((s->front + 1) % MAX == s->rear&&(s1->front + 1) % MAX == s1->rear)//队列为空 { return; } if (Getcount(s) > Getcount(s1))//队列A比队列B的元素多则将A导入B { while (s->rear!= (s->front+1)%MAX) { s1->data[s1->rear] = s->data[s->front]; s1->rear = (s1->rear + 1) % MAX;//队列A出 s->front = (s->front + 1) % MAX;//队列B入 } *e = s->data[s->rear - 1]; return; } if (Getcount(s)<Getcount(s1))//队列B比队列A的元素多则将B导入A { while ((s1->front + 1) % MAX!= s1->rear) { s->data[s->rear] = s1->data[s1->front]; s->rear = (s->rear + 1) % MAX;//队列A出 s1->front = (s1->front + 1) % MAX;//队列B入 } *e = s1->data[s1->rear - 1]; return; } if (Getcount(s)==1) { *e = s->data[s->rear - 1]; return; } else { *e = s1->data[s1->rear - 1]; return; } } int main() { int arr [5]= { 1, 2, 3, 4, 5 }; int len = sizeof(arr) / sizeof(*arr); circleQ QQ1; circleQ QQ2; InitcircleQ(&QQ1); InitcircleQ(&QQ2); Pushelem(&QQ1, arr, len); for (int i = 0; i < len; i++) { int e; Popelem(&QQ1, &QQ2, &e); printf("%d ", e); } system("pause"); return 0; }
问题四:元素出栈,入栈顺序的合法性。例如入栈序列(1,2,3,4,5),出栈序列(4,5,3,2,1)判断这个出栈顺序是否合法
解题思路:设置一个辅助栈,将入栈顺序中的元素依次按其入栈的顺序压入,注意,在压入的过程中和出栈序列中的元素出栈顺序依次从前往后比较,如果压入的元素等于出栈序列的前排元素则将其弹出,然后出栈序列指向下一个元素,继续比较一次栈顶是否相等,不相等则继续进行压栈。循环循环判断,最后当所以元素都进行压栈操作后栈不为空则非法,如果为空则合法。
代码如下(C语言实现)
#include<stdio.h> #include<stdlib.h> #include<malloc.h> #define MAX 10 #define ADD 10 typedef int Datatype; typedef struct stack { Datatype *base; Datatype *top; int capacity; }stack,*stackptr; void Iintsytack(stackptr s)//初始化栈 { s->base = (Datatype *)malloc(sizeof(Datatype)*MAX);//申请空间 if (NULL == s->base) { exit(0); } else { s->top = s->base; s->capacity = MAX; } } void Capacityif(stackptr s)//判满函数 { if (MAX == s->top - s->base)//判断是否栈满,如果满则扩容 { s->base = (Datatype *)realloc(s->base, sizeof(Datatype)*(s->capacity + ADD)); if (NULL == s->base) { exit(0); } s->top = s->base + s->capacity; s->capacity += ADD; } } int Getsize(stackptr s) { return s->top - s->base; } int judgesatck(stackptr s, Datatype *arr1, Datatype *arr2,int len1,int len2) { Capacityif(s);//如果栈满则扩容 if (len1 != len2 || len1 == 0) { return 0; } else { for (int i = 0; i < len1; i++) { *(s->top++) = *arr1++;//入栈 while (*(s->top - 1) == *arr2)//判断入栈元素是否和出栈数序中的第一个元素相等 { s->top--; arr2++; } } if (Getsize(s) == 0) { return 1; } else return 0; } } void popstack(stackptr s, Datatype *e)//弹栈 { if (s->top == s->base) { return; } *e = *(--s->top); } int main()//main()函数中为测试代码 { stack stacker; Iintsytack(&stacker); int arr1[] = { 1, 2, 3, 4, 5 }; int arr2[] = { 4, 5, 3, 2, 1 }; int len1 = sizeof(arr1) / sizeof(*arr1); int len2 = sizeof(arr2) / sizeof(*arr2); if (judgesatck(&stacker, arr1, arr2, len1, len2)) { printf("顺序合法\n"); } else { printf("顺序不合法\n"); } system("pause"); return 0; }测试如下:
1.入栈12345 出栈 45321
2.入栈12345 出栈45312
问题五:一个数组实现两个栈(栈共享)
解题思路:
这有三种实现方式:
1.奇偶栈,将数组下标为0当作第一个栈的栈低,下标为1当作第二个栈的栈低,将数组偶数位下标的看作第一个栈的储存空间,奇数位看作第二个栈的储存空间。
2.将数组的中间看作两个栈的栈低,入栈时分别向左右入栈,当任何一边满栈时就进行扩容
3.将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。
因为方法1和方法2都会浪费空间,利用率较低,所以我们只实现第三种栈
代码实现如下(C语言)
#include<stdio.h> #include<stdlib.h> #include<malloc.h> #define MAX 10 #define ADD 10 typedef int Datatype; typedef struct stack { Datatype *base1; Datatype *top1; Datatype *base2; Datatype *top2; int capacity; }stack,*stackptr; void Iintsytack(stackptr s)//初始化栈 { s->base1 = (Datatype *)malloc(sizeof(Datatype)*MAX);//申请空间 if (NULL == s->base1) { exit(0); } else { s->top1 = s->base1;//栈1 s->top2=s->base2 = s->base1 + MAX-1;//栈2指向最后一块空间 s->capacity = MAX; } } void pushstack1(stackptr s,Datatype e) { if (s->top1 == s->top2) { return; } *(s->top1++) = e; } void pushstack2(stackptr s, Datatype e) { if (s->top1 == s->top2) { return; } *(s->top2--) = e; } void popstack1(stackptr s, Datatype *e) { if (s->top1 - s->base1 == 0) { return; } *e = *(--s->top1); } void popstack2(stackptr s, Datatype *e) { if (s->base1 - s->top2== 0) { return; } *e = *(++s->top2); } int main()//main()函数中为测试代码 { int e,a; stack stacker; Iintsytack(&stacker); for (int i = 0; i < 4; i++) { pushstack1(&stacker, i); pushstack2(&stacker, i + 2); } for (int j = 0; j < 4; j++) { popstack1(&stacker,&e); printf("%d", e); } printf("\n"); for (int j = 0; j < 4; j++) { popstack2(&stacker, &a); printf("%d", a); } system("pause"); return 0; }
相关文章推荐
- 栈和队列相关面试题(2)
- 剑指offer编程题Java实现——面试题7相关题用两个队列实现一个栈
- 栈和队列相关面试题(3)
- 栈和队列 相关 面试题
- 栈和队列的相关面试题
- 栈和队列相关面试题(1)
- 【程序员面试宝典】栈和队列相关面试题
- 栈与队列相关面试题
- 栈和队列相关面试题2
- 面试题7—相关题目(两个队列实现栈)
- 栈和队列相关面试题(1)
- 栈和队列 相关 面试题
- 栈和队列相关面试题
- 队列和栈相关面试题总结
- Struts2相关的面试题整理分享
- 《剑指offer》面试题7:用两个栈实现队列
- uC/OS-II 函数之消息队列相关函数
- 面试题7 两个栈实现队列
- 算法面试题:使用两个堆栈实现一个队列
- Linux内核相关常见面试题