当前位置:   article > 正文

LeetCode —— 栈和队列相关的oj题(含循环队列)_oj双端队列

oj双端队列

目录

一、用队列实现栈

1.题干分析

2.动图解析 

3.代码实现

二、有效的括号

1.题干分析 

2.动图解析 

3.代码实现 

三、用栈实现队列 

1.题干分析 

2.动图解析 

3.代码实现 

四、设计循环队列 

1.题干分析 

2.代码实现

①数组实现

②链表实现


一、用队列实现栈

        请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

 

注意:

你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
 

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[ [ ], [1], [2], [ ], [ ], [ ] ]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False


链接:https://leetcode-cn.com/problems/implement-stack-using-queues

1.题干分析

        队列的特点---先进先出,后进后出;栈的特点---先进后出,后进先出; 用两个队列实现一个栈,那么他们入数据都是一样的,知识出数据的时候相反;为什么要用两个队列呢?假设q1和q2两个队列;q1队列用来入数据(入1,2,3,4),q2队列用来入q1队列的数据(就是依次取q1队列的队头的数据,入1,2,3),当q2队列只剩下一个数据(4)的时候,就把这个数据取出;数字4是后进队列的,此时取出就相当于数字4后进先出,这不就是栈的特点嘛。如果继续出数据,把q1里的数据入到q2里,当q1只剩下一个数据时,就出数据;那么两个队列实现一个栈就完成了;

如何创建一个栈呢?还要有两个队列呢? 

我们之前在C语言实现的队列中,是这样定义的:

  1. typedef int QDataType;
  2. typedef struct QueueNode
  3. {
  4. struct QueueNode* next;
  5. QDataType data;
  6. }QueueNode;
  7. typedef struct Queue
  8. {
  9. QueueNode* head;//队头
  10. QueueNode* tail;//队尾
  11. }Queue;

题目中给了这样的代码:

  1. typedef struct {
  2. } MyStack;

这是栈的结构体;栈是用两个队列实现的,那么栈里面肯定是需要两个队列来实现的;

  1. typedef struct {
  2. Queue q1;//队列1
  3. Queue q2;//队列2
  4. } MyStack;

因为嵌套了几个结构体,很容易搞混,尤其是在调用的时候,下面是关系图:

2.动图解析 

3.代码实现

在没有学习C++之前,用C语言实现这道题,我们可以将C语言实现的队列直接调过来 ;

  1. typedef int QDataType;
  2. typedef struct QueueNode
  3. {
  4. struct QueueNode* next;
  5. QDataType data;
  6. }QueueNode;
  7. typedef struct Queue
  8. {
  9. QueueNode* head;
  10. QueueNode* tail;
  11. }Queue;
  12. //队列的初始化
  13. void QueueInit(Queue* pq);
  14. //队列的销毁
  15. void QueueDestroy(Queue* pq);
  16. //队尾入队列
  17. void QueuePush(Queue* pq, QDataType x);
  18. // 队头出队列
  19. void QueuePop(Queue* pq);
  20. //取队头的数据
  21. QDataType QueueFront(Queue* pq);
  22. //取队尾的数据
  23. QDataType QueueBack(Queue* pq);
  24. //计算有多少个数据
  25. int QueueSize(Queue* pq);
  26. //判断队列是否为空
  27. bool QueueEmpty(Queue* pq);
  28. //队列的初始化
  29. void QueueInit(Queue* pq)
  30. {
  31. assert(pq);
  32. pq->head = NULL;
  33. pq->tail = NULL;
  34. }
  35. //队列的销毁
  36. void QueueDestroy(Queue* pq)
  37. {
  38. assert(pq);
  39. QueueNode* cur = pq->head;
  40. while (cur != NULL)
  41. {
  42. QueueNode* next = cur->next;
  43. free(cur);
  44. cur = next;
  45. }
  46. pq->head = pq->tail = NULL;
  47. }
  48. //队尾入队列(尾插)
  49. void QueuePush(Queue* pq, QDataType x)
  50. {
  51. assert(pq);
  52. QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
  53. newnode->data = x;
  54. newnode->next = NULL;
  55. if (pq->head == NULL)
  56. {
  57. pq->head = pq->tail = newnode;
  58. }
  59. else
  60. {
  61. pq->tail->next = newnode;
  62. pq->tail = newnode;
  63. }
  64. }
  65. // 队头出队列(删除数据)
  66. void QueuePop(Queue* pq)
  67. {
  68. assert(pq);
  69. assert(!QueueEmpty(pq));
  70. QueueNode* next = pq->head->next;
  71. free(pq->head);
  72. pq->head = next;
  73. //此时head和tail同时指向最后一个空间,释放head后,要注意也要把tail释放了
  74. if (pq->head == NULL)
  75. {
  76. pq->tail = NULL;
  77. }
  78. }
  79. //取队头的数据
  80. QDataType QueueFront(Queue* pq)
  81. {
  82. assert(pq);
  83. assert(!QueueEmpty(pq));
  84. return pq->head->data;
  85. }
  86. //取队尾的数据
  87. QDataType QueueBack(Queue* pq)
  88. {
  89. assert(pq);
  90. assert(!QueueEmpty(pq));
  91. return pq->tail->data;
  92. }
  93. //计算有多少个数据
  94. int QueueSize(Queue* pq)
  95. {
  96. assert(pq);
  97. int n = 0;
  98. QueueNode* cur = pq->head;
  99. while (cur)
  100. {
  101. ++n;
  102. cur = cur->next;
  103. }
  104. return n;
  105. }
  106. //判断队列是否为空
  107. bool QueueEmpty(Queue* pq)
  108. {
  109. assert(pq);
  110. return pq->head == NULL;
  111. }
  112. typedef struct {
  113. Queue q1;
  114. Queue q2;
  115. } MyStack;
  116. //栈的创建
  117. MyStack* myStackCreate() {
  118. MyStack* st = (MyStack*)malloc(sizeof(MyStack));
  119. QueueInit(&st->q1);
  120. QueueInit(&st->q2);
  121. return st;
  122. }
  123. //数据入栈
  124. void myStackPush(MyStack* obj, int x) {
  125. if(!QueueEmpty(&obj->q1))
  126. {
  127. QueuePush(&obj->q1,x);
  128. }
  129. else
  130. {
  131. QueuePush(&obj->q2,x);
  132. }
  133. }
  134. //数据出栈
  135. int myStackPop(MyStack* obj) {
  136. Queue* emptyQ = &obj->q1;
  137. Queue* noneemptyQ = &obj->q2;
  138. if(!QueueEmpty(&obj->q1))
  139. {
  140. emptyQ = &obj->q2;
  141. noneemptyQ = &obj->q1;
  142. }
  143. while(QueueSize(noneemptyQ) > 1)
  144. {
  145. QueuePush(emptyQ,QueueFront(noneemptyQ));
  146. QueuePop(noneemptyQ);
  147. }
  148. int top = QueueFront(noneemptyQ);
  149. QueuePop(noneemptyQ);
  150. return top;
  151. }
  152. //栈顶元素
  153. int myStackTop(MyStack* obj) {
  154. //队列的尾就是栈的顶
  155. if(!QueueEmpty(&obj->q1))
  156. {
  157. return QueueBack(&obj->q1);
  158. }
  159. else
  160. {
  161. return QueueBack(&obj->q2);
  162. }
  163. }
  164. //判断栈是否为空
  165. bool myStackEmpty(MyStack* obj) {
  166. return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
  167. }
  168. //栈的销毁
  169. void myStackFree(MyStack* obj) {
  170. QueueDestroy(&obj->q1);
  171. QueueDestroy(&obj->q2);
  172. free(obj);
  173. }

二、有效的括号

 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

示例 1:

输入:s = " ( ) "
输出:true
示例 2:

输入:s = " ( ) [ ] { } "
输出:true
示例 3:

输入:s = " ( ] "
输出:false
示例 4:

输入:s = " ( [ ) ] "
输出:false
示例 5:

输入:s = " { [ ] } "
输出:true


链接:https://leetcode-cn.com/problems/valid-parentheses

1.题干分析 

 本题向要表达的意思就是给定了一个含有左右括号的字符串,如果形如‘( )’则为有效,形如‘( }’则为无效;我们该如何入手呢?,我们可以用栈的特点来实现,先进栈的左括号后匹配,配对成功则删除这对括号,直至全部匹配成功;

2.动图解析 

3.代码实现 

  1. typedef char STDataType;
  2. typedef struct Stack
  3. {
  4. STDataType* a;
  5. int top;//栈顶
  6. int capacity;
  7. }ST;
  8. //栈的初始化
  9. void StackInit(ST* ps);
  10. //栈的销毁
  11. void StackDestroy(ST* ps);
  12. //栈的栈顶插入
  13. void StackPush(ST* ps, STDataType x);
  14. //栈的删除
  15. void StackPop(ST* ps);
  16. //取栈顶的数据
  17. STDataType StackTop(ST* ps);
  18. //栈的元素个数
  19. int StackSize(ST* ps);
  20. //判断栈是不是空
  21. bool StackEmpty(ST* ps);
  22. //栈的初始化
  23. void StackInit(ST* ps)
  24. {
  25. assert(ps);
  26. ps->a = NULL;
  27. ps->top = 0;
  28. ps->capacity = 0;
  29. }
  30. //栈的销毁
  31. void StackDestroy(ST* ps)
  32. {
  33. assert(ps);
  34. free(ps->a);
  35. ps->a = NULL;
  36. ps->capacity = ps->top = 0;
  37. }
  38. //栈的栈顶插入
  39. void StackPush(ST* ps, STDataType x)
  40. {
  41. assert(ps);
  42. if (ps->top == ps->capacity)
  43. {
  44. int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
  45. STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
  46. if (tmp == NULL)
  47. {
  48. printf("realloc fail\n");
  49. exit(-1);
  50. }
  51. ps->a = tmp;
  52. ps->capacity = newCapacity;
  53. }
  54. ps->a[ps->top] = x;
  55. ps->top++;
  56. }
  57. //栈的删除
  58. void StackPop(ST* ps)
  59. {
  60. assert(ps);
  61. assert(!StackEmpty(ps));
  62. ps->top--;
  63. }
  64. //取栈顶的数据
  65. STDataType StackTop(ST* ps)
  66. {
  67. assert(ps);
  68. assert(!StackEmpty(ps));
  69. return ps->a[ps->top - 1];
  70. }
  71. //栈的元素个数
  72. int StackSize(ST* ps)
  73. {
  74. assert(ps);
  75. return ps->top;
  76. }
  77. //判断栈是不是空
  78. bool StackEmpty(ST* ps)
  79. {
  80. assert(ps);
  81. return ps->top == 0;
  82. }
  83. bool isValid(char * s){
  84. ST st;
  85. StackInit(&st);
  86. while(*s)
  87. {
  88. //入左括号
  89. if(*s == '(' || *s== '{' || *s== '[')
  90. {
  91. StackPush(&st,*s);
  92. ++s;
  93. }
  94. else
  95. {
  96. //遇到右括号,但是栈里面没有数据,说明前面没有左括号,不匹配
  97. if(StackEmpty(&st))
  98. {
  99. StackDestroy(&st);
  100. return false;
  101. }
  102. //取栈顶的数据,进行比对
  103. STDataType top = StackTop(&st);
  104. StackPop(&st);
  105. if((*s == ')' && top != '(')
  106. ||(*s == '}' && top != '{')
  107. ||(*s == ']' && top != '['))
  108. {
  109. StackDestroy(&st);
  110. return false;
  111. }
  112. else
  113. {
  114. s++;
  115. }
  116. }
  117. }
  118. //如果不是空,说明还有左括号未出;
  119. //没有匹配返回的是false
  120. bool ret = StackEmpty(&st);
  121. StackDestroy(&st);
  122. return ret;
  123. }

三、用栈实现队列 

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:

你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

 

示例 1:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false


连接:https://leetcode-cn.com/problems/implement-queue-using-stacks

1.题干分析 

 用两个栈来才实现队列,一个栈先入数据,另一个栈用来存第一个栈的数据,如:第一个栈如1,2,3,4,第二个栈从第一个栈的栈顶拿数据入,即为4,3,2,1;,这时候在取第二个栈的栈顶数据,就符合原来1,2,3,4先进先出的顺序,即队列的特点

2.动图解析 

3.代码实现 

  1. typedef int STDataType;
  2. typedef struct Stack
  3. {
  4. STDataType* a;
  5. int top;//栈顶
  6. int capacity;
  7. }ST;
  8. //栈的初始化
  9. void StackInit(ST* ps);
  10. //栈的销毁
  11. void StackDestroy(ST* ps);
  12. //栈的栈顶插入
  13. void StackPush(ST* ps, STDataType x);
  14. //栈的删除
  15. void StackPop(ST* ps);
  16. //取栈顶的数据
  17. STDataType StackTop(ST* ps);
  18. //栈的元素个数
  19. int StackSize(ST* ps);
  20. //判断栈是不是空
  21. bool StackEmpty(ST* ps);
  22. //栈的初始化
  23. void StackInit(ST* ps)
  24. {
  25. assert(ps);
  26. ps->a = NULL;
  27. ps->top = 0;
  28. ps->capacity = 0;
  29. }
  30. //栈的销毁
  31. void StackDestroy(ST* ps)
  32. {
  33. assert(ps);
  34. free(ps->a);
  35. ps->a = NULL;
  36. ps->capacity = ps->top = 0;
  37. }
  38. //栈的栈顶插入
  39. void StackPush(ST* ps, STDataType x)
  40. {
  41. assert(ps);
  42. if (ps->top == ps->capacity)
  43. {
  44. int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
  45. STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
  46. if (tmp == NULL)
  47. {
  48. printf("realloc fail\n");
  49. exit(-1);
  50. }
  51. ps->a = tmp;
  52. ps->capacity = newCapacity;
  53. }
  54. ps->a[ps->top] = x;
  55. ps->top++;
  56. }
  57. //栈的删除
  58. void StackPop(ST* ps)
  59. {
  60. assert(ps);
  61. assert(!StackEmpty(ps));
  62. ps->top--;
  63. }
  64. //取栈顶的数据
  65. STDataType StackTop(ST* ps)
  66. {
  67. assert(ps);
  68. assert(!StackEmpty(ps));
  69. return ps->a[ps->top - 1];
  70. }
  71. //栈的元素个数
  72. int StackSize(ST* ps)
  73. {
  74. assert(ps);
  75. return ps->top;
  76. }
  77. //判断栈是不是空
  78. bool StackEmpty(ST* ps)
  79. {
  80. assert(ps);
  81. return ps->top == 0;
  82. }
  83. typedef struct {
  84. ST pushST;
  85. ST popST;
  86. } MyQueue;
  87. //队列的创建
  88. MyQueue* myQueueCreate() {
  89. MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
  90. StackInit(&q->pushST);
  91. StackInit(&q->popST);
  92. return q;
  93. }
  94. void myQueuePush(MyQueue* obj, int x) {
  95. StackPush(&obj->pushST,x);
  96. }
  97. //取队头数据
  98. int myQueuePop(MyQueue* obj) {
  99. //如果popST中没有数据,将pushST中的数据导过去
  100. //popST中的数据就符合先进先出的顺序了
  101. if(StackEmpty(&obj->popST))
  102. {
  103. while(!StackEmpty(&obj->pushST))
  104. {
  105. StackPush(&obj->popST,StackTop(&obj->pushST));
  106. StackPop(&obj->pushST);
  107. }
  108. }
  109. int front = StackTop(&obj->popST);
  110. StackPop(&obj->popST);
  111. return front;
  112. }
  113. //返回队列开头的元素
  114. int myQueuePeek(MyQueue* obj) {
  115. if(StackEmpty(&obj->popST))
  116. {
  117. while(!StackEmpty(&obj->pushST))
  118. {
  119. StackPush(&obj->popST,StackTop(&obj->pushST));
  120. StackPop(&obj->pushST);
  121. }
  122. }
  123. return StackTop(&obj->popST);
  124. }
  125. //判断队列是否为空
  126. bool myQueueEmpty(MyQueue* obj) {
  127. return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
  128. }
  129. //队列销毁
  130. void myQueueFree(MyQueue* obj) {
  131. StackDestroy(&obj->pushST);
  132. StackDestroy(&obj->popST);
  133. free(obj);
  134. }

四、设计循环队列 

         设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。

 

示例:

MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3
circularQueue.enQueue(1);  // 返回 true
circularQueue.enQueue(2);  // 返回 true
circularQueue.enQueue(3);  // 返回 true
circularQueue.enQueue(4);  // 返回 false,队列已满
circularQueue.Rear();  // 返回 3
circularQueue.isFull();  // 返回 true
circularQueue.deQueue();  // 返回 true
circularQueue.enQueue(4);  // 返回 true
circularQueue.Rear();  // 返回 4


链接:https://leetcode-cn.com/problems/design-circular-queue

1.题干分析 

什么是循环队列?循环队列与普通队列的差异是什么? 

  

普通队列我们可以采用链表和顺序表的方式进行实现,之前的博客中说到,顺序表实现队列,由于数据在出队列的时候需要每次挪动数据代价比较大;因而我们选择了链表来实现;

如果非要采用顺序存储呢?建议采用循环队列的形式;

假设:初始化创建空队时,令head(头指针)和tail(尾指针)为0;,每当插入新的数据时,尾指针tail增1;每当删除队列头数据时,头指针head减1;在非空队列中,head始终指向队列的头,tail始终指向队列的尾的下一个位置;如下图所示;

循环队列,就是头尾相接 ;如果是链表,实现循环,我们可以想到一个循环链表,尾结点不指向空,指向头结点就可以了;那么数组怎么实现头尾相接呢?

重点: 

        循环队列,无论使用数组实现还是链表实现,都要多开一个空间,也就意味着,要是存K个数据的循环队列,要开k+1个空间,否则无法判空和判满;

开辟k个空间:

满和空条件都是一样的,无法判端满;(数组也是如此)

开辟k+1个空间:

2. 代码实现

①数组实现

  1. typedef struct {
  2. int* a;
  3. int k;
  4. int front;
  5. int tail;
  6. } MyCircularQueue;
  7. bool myCircularQueueIsEmpty(MyCircularQueue* obj);
  8. bool myCircularQueueIsFull(MyCircularQueue* obj);
  9. MyCircularQueue* myCircularQueueCreate(int k) {
  10. MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
  11. cq->a = (int*)malloc(sizeof(int)*(k+1));//开辟k+1个空间
  12. cq->front = cq->tail = 0;
  13. cq->k = k;
  14. return cq;
  15. }
  16. //入数据
  17. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
  18. if(myCircularQueueIsFull(obj))
  19. return false;
  20. obj->a[obj->tail] = value;
  21. ++obj->tail;
  22. obj->tail %= (obj->k+1);
  23. return true;
  24. }
  25. //出数据
  26. bool myCircularQueueDeQueue(MyCircularQueue* obj) {
  27. if(myCircularQueueIsEmpty(obj))
  28. return false;
  29. ++obj->front;
  30. obj->front%=(obj->k+1);
  31. return true;
  32. }
  33. //取队头
  34. int myCircularQueueFront(MyCircularQueue* obj) {
  35. if(myCircularQueueIsEmpty(obj))
  36. return -1;
  37. return obj->a[obj->front];
  38. }
  39. //取队尾
  40. int myCircularQueueRear(MyCircularQueue* obj) {
  41. if(myCircularQueueIsEmpty(obj))
  42. return -1;
  43. if(obj->tail ==0)
  44. return obj->a[obj->k];
  45. else
  46. return obj->a[obj->tail-1];
  47. /*
  48. int i = (obj->tail + obj->k) % (obj->k+1);
  49. return obj->a[i];
  50. */
  51. }
  52. //判空
  53. bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
  54. return obj->front == obj->tail;
  55. }
  56. //判满
  57. bool myCircularQueueIsFull(MyCircularQueue* obj) {
  58. return (obj->tail+1) % (obj->k+1) == obj->front;
  59. }
  60. //销毁
  61. void myCircularQueueFree(MyCircularQueue* obj) {
  62. free(obj->a);
  63. free(obj);
  64. }

② 链表实现

相比数组,链表不可以直接malloc k+1个节点;我们需要通过循环去开辟; 

  1. typedef int CirQDataType;
  2. typedef struct CirQNode
  3. {
  4. CirQDataType Data;
  5. struct CirQNode* next;
  6. }CirQNode;
  7. typedef struct {
  8. int k;
  9. CirQNode* head;
  10. CirQNode* tail;
  11. } MyCircularQueue;
  12. bool myCircularQueueIsEmpty(MyCircularQueue* obj);
  13. bool myCircularQueueIsFull(MyCircularQueue* obj);
  14. //循环队列的初始化
  15. MyCircularQueue* myCircularQueueCreate(int k) {
  16. MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
  17. CirQNode* cur = (CirQNode*)malloc(sizeof(CirQNode));
  18. cq->k = k;
  19. cq->head = cq->tail = cur;
  20. //创建好一个结点后,在后面循环创建k个结点
  21. while(k--)
  22. {
  23. CirQNode* newnode = (CirQNode*)malloc(sizeof(CirQNode));
  24. CirQNode* NewTail = cq->tail;//记录新的尾
  25. NewTail->next = newnode;//把申请的结点链到新的尾上
  26. newnode->next = cq->head;//新结点链到头结点
  27. cq->tail=newnode;//自己成为新的尾
  28. }
  29. cq->tail=cq->tail->next;//让tail回到原来的位置,也可不加,因为循环,只是个人看着不舒服
  30. cq->head = cq->tail;
  31. return cq;
  32. }
  33. //循环队列的入数据
  34. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
  35. if(myCircularQueueIsFull(obj))
  36. return false;
  37. //依次入数据,tail向后走
  38. obj->tail->Data = value;
  39. obj->tail = obj->tail->next;
  40. return true;
  41. }
  42. //循环队列的出数据
  43. bool myCircularQueueDeQueue(MyCircularQueue* obj) {
  44. if(myCircularQueueIsEmpty(obj))
  45. return false;
  46. obj->head = obj->head->next;
  47. return true;
  48. }
  49. //循环队列取队头数据
  50. int myCircularQueueFront(MyCircularQueue* obj) {
  51. if(myCircularQueueIsEmpty(obj))
  52. return -1;
  53. return obj->head->Data;
  54. }
  55. //循环队列取队尾数据
  56. int myCircularQueueRear(MyCircularQueue* obj) {
  57. if(myCircularQueueIsEmpty(obj))
  58. return -1;
  59. //tail的前有个位置的结点就是队尾的数据
  60. CirQNode* prev = obj->head;
  61. while(prev->next != obj->tail)
  62. {
  63. prev = prev->next;
  64. }
  65. return prev->Data;
  66. }
  67. //循环队列判空
  68. bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
  69. return obj->head == obj->tail;
  70. }
  71. //循环队列判满
  72. bool myCircularQueueIsFull(MyCircularQueue* obj) {
  73. return obj->tail->next == obj->head;
  74. }
  75. //循环队列销毁
  76. void myCircularQueueFree(MyCircularQueue* obj) {
  77. while(obj->head != obj->tail)
  78. {
  79. CirQNode* cur = obj->head->next;
  80. free(obj->head);
  81. obj->head = cur;
  82. }
  83. free(obj->head);
  84. free(obj);
  85. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/620912
推荐阅读
相关标签
  

闽ICP备14008679号