用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例 1:
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]
示例 2:
输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
提示:
1 <= values <= 10000
最多会对 appendTail、deleteHead 进行 10000 次调用
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof
【解题思路】
用两个栈实现队列:
- 栈无法实现队列功能: 栈底元素(对应队首元素)无法直接删除,需要将上方所有元素出栈。
- 双栈可实现列表倒序: 设有含三个元素的栈 A = [1,2,3] 和空栈 B = []。若循环执行 A 元素出栈并添加入栈 B ,直到栈 A 为空,则 A = [] , B = [3,2,1],即 栈 B 元素实现栈 A 元素倒序 。
- 利用栈 B 删除队首元素: 倒序后,B 执行出栈则相当于删除了 A 的栈底元素,即对应队首元素。
【提交代码】
1 typedef struct st_stack{ 2 int size; 3 int *data; 4 int top; 5 }T_Stack; 6 7 typedef struct { 8 T_Stack *s1; 9 T_Stack *s2; 10 } CQueue; 11 12 13 int StackInit( T_Stack *ptStack, int *data, int size) 14 { 15 ptStack->size = size; 16 ptStack->data = data; 17 ptStack->top = 0; 18 19 return 0; 20 } 21 22 int StackPush( T_Stack *ptStack, int data ) 23 { 24 if( ptStack->top == ptStack->size ) 25 { 26 return -1; 27 } 28 29 ptStack->data[ptStack->top++] = data; 30 31 return 0; 32 } 33 34 int StackPop( T_Stack *ptStack, int *data ) 35 { 36 if( ptStack->top == 0 ) 37 { 38 return -1; 39 } 40 41 *data = ptStack->data[--ptStack->top]; 42 43 return 0; 44 } 45 46 int StackTop( T_Stack *ptStack, int *data ) 47 { 48 if( ptStack->top == 0 ) 49 { 50 return -1; 51 } 52 53 *data = ptStack->data[ptStack->top - 1]; 54 55 return 0; 56 } 57 58 int StackIsEmpty( T_Stack *ptStack ) 59 { 60 return ( ptStack->top == 0 ); 61 } 62 63 int StackIsFull( T_Stack *ptStack ) 64 { 65 return ( ptStack->top == ptStack->size ); 66 } 67 68 #define QUEUE_SIZE_MAX ( 10000 ) 69 70 CQueue* cQueueCreate() { 71 int *data1; 72 int *data2; 73 T_Stack *s1; 74 T_Stack *s2; 75 CQueue *queue; 76 77 data1 = (int *)malloc( sizeof(int) * QUEUE_SIZE_MAX ); 78 data2 = (int *)malloc( sizeof(int) * QUEUE_SIZE_MAX ); 79 80 s1 = (T_Stack *)malloc( sizeof(T_Stack)); 81 s2 = (T_Stack *)malloc( sizeof(T_Stack)); 82 83 StackInit( s1, data1, QUEUE_SIZE_MAX ); 84 StackInit( s2, data2, QUEUE_SIZE_MAX ); 85 86 queue = (CQueue *)malloc( sizeof(CQueue) ); 87 88 queue->s1 = s1; 89 queue->s2 = s2; 90 91 return queue; 92 } 93 94 int cQueueAppendTail(CQueue* obj, int value) { 95 if( StackIsFull( obj->s1) ) 96 { 97 return -1; 98 } 99 100 if( StackPush( obj->s1, value ) != 0 ) 101 { 102 return -1; 103 } 104 105 return 0; 106 } 107 108 int cQueueDeleteHead(CQueue* obj) { 109 int tmp; 110 111 // 1.当B不为空,则B中仍有已完成倒叙的元素,因此直接返回B的栈顶元素 112 if( !StackIsEmpty( obj->s2 ) ) 113 { 114 if( StackPop( obj->s2, &tmp ) != 0) 115 { 116 return -1; 117 } 118 119 return tmp; 120 } 121 122 // 2.当A也为空,则两个栈都为空,无元素,因此返回-1 123 if( StackIsEmpty( obj->s1 ) ) 124 { 125 return -1; 126 } 127 128 // 3.将A元素全部转移至栈B中,实现元素倒叙,并返回栈B的栈顶元素 129 while( !StackIsEmpty( obj->s1) && !StackIsFull( obj->s2 ) ) 130 { 131 StackPop( obj->s1, &tmp ); 132 StackPush( obj->s2, tmp ); 133 } 134 135 if( !StackIsEmpty( obj->s1) ) // 如果A没有完全转移,则还是错误的 136 { 137 return -1; 138 } 139 140 StackPop( obj->s2, &tmp ); 141 142 return tmp; 143 } 144 145 void cQueueFree(CQueue* obj) { 146 free(obj->s1->data); 147 free(obj->s2->data); 148 free(obj->s1); 149 free(obj->s2); 150 free(obj); 151 } 152 153 /** 154 * Your CQueue struct will be instantiated and called as such: 155 * CQueue* obj = cQueueCreate(); 156 * cQueueAppendTail(obj, value); 157 158 * int param_2 = cQueueDeleteHead(obj); 159 160 * cQueueFree(obj); 161 */