chapter_stack_and_queue/queue/ #149
Replies: 59 comments 66 replies
-
针对Java的Queue类补充一些知识点:
队列除了基本的 Collection 操作外,还提供特有的插入、提取和检查操作(如上)。每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(null 或 false,具体取决于操作)。 |
Beta Was this translation helpful? Give feedback.
-
循环数组 -🐂的 |
Beta Was this translation helpful? Give feedback.
-
pop = que.popleft() 这里python的实现应该是pop = que.pop(0),3.9.0版本无popleft用法,pooleft是用于collections中的deque对象 |
Beta Was this translation helpful? Give feedback.
-
队列一章中,包括双向队列,有些地方入队用 push , 有些地方入队用 offer,建议统一一下使文章更严谨。比如统一使用 Java 中的用词 offer |
Beta Was this translation helpful? Give feedback.
-
class typing.Deque 3.9 版后已移除,这个类型注解会导致程序报错 import typing
import collections
que: Deque[int] = collections.deque()
-------------------------------------------------
NameError: name 'Deque' is not defined |
Beta Was this translation helpful? Give feedback.
-
打卡,手敲了一遍链表和循环数组实现队列,不过我好像只能跟着敲。 |
Beta Was this translation helpful? Give feedback.
-
基于链表实现的队列进行入队操作,如果队列不为空,则将该节点添加到尾节点后中的else语句里这两句不理解 rear.next = node; rear = node;,不应该只用rear.next = node;就行了嘛 |
Beta Was this translation helpful? Give feedback.
-
问题:执行到 rear.next = node;(1处)这里后,当此时push的是2的时候,real.next.val = 2这个很好理解,为什么front.next.val = 2 也会赋值呢?在push的时候,又没有写front.next = node; 这里我不太理解~
/* 入队 */ |
Beta Was this translation helpful? Give feedback.
-
用数组实现队列的三张演示图中的第二张,也就是push操作,并没有提及rear自增1的操作:
|
Beta Was this translation helpful? Give feedback.
-
问题:环形数组队列的有效长度不应该是Maxsize=len(self.__nums)-1 |
Beta Was this translation helpful? Give feedback.
-
res = [0] * self.size()这种初始化队列的方式,会导致res 的每个元素引用相同的地址吗,就是如果我改动res[0]=1,那么res[1]、res[2]、...会不会因为存放的是相同的地址,导致都变为1 |
Beta Was this translation helpful? Give feedback.
-
在5.2.2的第1节基于链表的实现,C语言代码的打印队列函数中,for循环语句条件queue->front != queue->rear是用来检测队列是否为空吗?但是如果队列中只有一个元素,好像就会打印不出那个单独的元素 |
Beta Was this translation helpful? Give feedback.
-
环形数组队列扩容 /* 入队 */
push(num) {
if (this.size === this.capacity) {
this.extendCapacity();
}
// ...
}
/* 扩容 */
extendCapacity() {
const extraSize = Math.round(this.capacity * 0.5);
const arr = new Array(extraSize);
this.#nums = this.toArray().concat(...arr);
this.#front = 0;
this.capacity += extraSize;
} |
Beta Was this translation helpful? Give feedback.
-
c++链表实现的队列,入队push()那里我有两个疑问: |
Beta Was this translation helpful? Give feedback.
-
/* 出队 */ |
Beta Was this translation helpful? Give feedback.
-
这个用“环形数组”实现队列真的太巧妙了,各种操作刚好保证了下标不会溢出,而且数据在数组里都是连续存储的,也不会被覆盖或者打印了内存里的垃圾值(如 python 里默认给的0,C 里该地址上的随机值……) |
Beta Was this translation helpful? Give feedback.
-
你好,在 队列实现 => 基于链表的实现章节 python代码中 def pop(self) -> int:
"""出队"""
num = self.peek()
# 删除头节点
self._front = self._front.next
self._size -= 1
return num 是否需要考虑当队列中只有1个元素的情况,文章中的 # 出队
def pop(self) -> int:
num = self.peek()
if self.size() == 1:
self._front = None
self._rear = None
else:
self._front = self._front.next
self._size -= 1
return num |
Beta Was this translation helpful? Give feedback.
-
在 hello-algo 里面的基于环形数组实现的队列用c语言在vim上运行之后最后的答案是有问题的 |
Beta Was this translation helpful? Give feedback.
-
在测试环形数组那一节得出来的答案有问题的。 |
Beta Was this translation helpful? Give feedback.
-
/* 入队 */ rear.next = node; 这两行还是理解了很长时间 |
Beta Was this translation helpful? Give feedback.
-
#ifndef __CUSTOMQUEUE_HPP__
#define __CUSTOMQUEUE_HPP__
/**
* @file customQueue.hpp
* @brief 基于数组和链表实现队列
*/
#include <cstdint>
#include <memory>
#include <stdexcept>
template<typename T, template<typename> typename Container>
class customQueue
{
public:
void push_back(const T& v){m_elements.push_back(v);}
void pop_front() {m_elements.pop_front();}
const T& front() const {return m_elements.front();}
T& front() {return const_cast<T&>(const_cast<const customQueue*>(this)->front());}
bool empty() const {return m_elements.empty();}
std::size_t size() const {return m_elements.size();}
private:
Container<T> m_elements;
};
template<typename T>
class listContainer
{
struct linknode
{
T value;
std::shared_ptr<linknode> next;
linknode(const T& v, std::shared_ptr<linknode> node):value(v), next(node){}
};
public:
void push_back(const T& v)
{
if (!m_front && !m_rear)
{
m_front = std::make_shared<linknode>(v, m_rear);
m_rear = m_front;
}
else
{
m_rear->next = std::make_shared<linknode>(v, nullptr);
m_rear = m_rear->next;
}
++m_size;
}
void pop_front()
{
if (empty())
return;
if (m_front == m_rear)
{
m_front = nullptr, m_rear = nullptr;
--m_size;
return;
}
m_front = m_front->next;
--m_size;
}
const T& front() const {return m_front->value;}
bool empty() const {return m_size == 0;}
std::size_t size() const {return m_size;}
private:
std::size_t m_size{0};
std::shared_ptr<linknode> m_front{nullptr};
std::shared_ptr<linknode> m_rear{nullptr};
};
template<typename T>
class arrayContainer
{
public:
arrayContainer(std::size_t capacity = 100):m_capacity(capacity)
{
m_array = std::make_unique<T[]>(m_capacity);
}
void push_back(const T& v)
{
if (m_size == m_capacity && !realloc())
return;
auto rear = (m_front + m_size) % m_capacity;
m_array[rear] = v;
++m_size;
}
void pop_front()
{
if (empty())
return;
m_front = (m_front + 1) % m_capacity;
--m_size;
}
const T& front() const
{
if (empty())
throw std::out_of_range("container is empty");
return m_array[m_front];
}
bool empty() const {return m_size == 0;}
std::size_t size() const {return m_size;}
bool realloc()
{
auto new_capacity = m_capacity * 2;
auto new_array = std::make_unique<T[]>(new_capacity);
if (!new_array)
return false;
std::copy(&m_array[0], &m_array[m_size - 1], &new_array[0]);
m_array = std::move(new_array);
m_capacity = new_capacity;
return true;
}
private:
std::size_t m_size{0};
std::size_t m_capacity{0};
std::unique_ptr<T[]> m_array;
std::size_t m_front{0};
};
template<typename T>
using queueByList = customQueue<T, listContainer>;
template<typename T>
using queueByArray = customQueue<T, arrayContainer>;
#endif |
Beta Was this translation helpful? Give feedback.
-
分享一个我在引入扩容机制的时候遇到的问题吧。一开始我在尝试用.size()去处理扩容问题,但是会遇到如下问题: 所以要解决这个就是要在push(6)的时候就扩容,也就是对push也计数并根据push的个数来触发扩容,这样就可以解决这个问题。 |
Beta Was this translation helpful? Give feedback.
-
成果展示 typedef struct ArrayQueue *new_array_queue()
} // 访问队首元素 // 出队 /* 析构函数 */ int main(int argc, char const *argv[])
} |
Beta Was this translation helpful? Give feedback.
-
链表实现的队列pop函数可以优化下: def pop(self) -> int:
num = self.peek()
self._front = self._front.next
self._size -= 1
# 补充空队列时的尾指针重置
if self._size == 0:
self._rear = None # 新增逻辑
return num |
Beta Was this translation helpful? Give feedback.
-
对指针不熟理解链表实现的队列还是有点难度。。。 /// <summary>
/// 数组队列
/// </summary>
/// <typeparam name="T"></typeparam>
public class CustomArrayQueue<T>
{
private readonly T[] _array = new T[10];
private int _count = 0;
private int _headIndex = 0;
private int TailIndex => _headIndex + _count;
public int Capacity => _array.Length;
public int Count => _count;
public void Enqueue(T value)
{
if (_count == _array.Length)
throw new InvalidOperationException("队列已满");
_array[TailIndex % Capacity] = value;
_count++;
}
public T Dequeue()
{
var res = Peek();
_array[_headIndex % Capacity] = default!;
_headIndex++;
_count--;
return res;
}
public T Peek()
{
if (_count == 0)
throw new InvalidOperationException("队列为空");
return _array[_headIndex % Capacity];
}
} |
Beta Was this translation helpful? Give feedback.
-
使用C语言中的void* 模拟其他语言中的泛型实现队列,确保队列的通用性。 #include "ListNode.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LISTNODE_GENERIC
#ifdef LISTNODE_GENERIC
ListNode *newListNode(void *value,size_t size){
ListNode *node = malloc(sizeof(ListNode));
if(!node){
printf("Memory allocation failed\n");
exit(EXIT_FAILURE);
}
node->value = malloc(size);
if(!node->value){
printf("Memory allocation failed\n");
exit(EXIT_FAILURE);
}
memcpy(node->value,value,size);
node->elementSize = size;
node->next = NULL;
return node;
}
ListNode *addListNode(ListNode *head, void *value, size_t size){
ListNode *newNode = newListNode(value,size);
newNode->next = head;
return newNode;
}
ListNode *delListNode(ListNode *head, void *value,size_t size){
ListNode *previous =NULL;
ListNode *current = head;
while(current !=NULL &¤t->elementSize ==size&&memcmp(current->value,value,size)){
previous = current;
current = current->next;
}
if(current ==NULL){
printf("未找到相关值");
return head;
}
if(previous ==NULL){
head = current->next;
}
else{
previous->next = current->next;
}
free(current->value);
free(current);
return head;
}
ListNode * delListNodeByIndex(ListNode *head, int index){
if(!head || index<0){
printf("Invalid index\n");
return head;
}
ListNode *pre = NULL;
ListNode *cur = head;
int currentIndex = 0;
while(!cur && currentIndex<index){
pre=cur;
cur=cur->next;
currentIndex++;
}
if(!cur){
printf("Index out of bounds\n");
return head;
}
if(pre ==NULL){
head = cur->next;
}
else{
pre->next = cur->next;
}
free(cur->value);
free(cur);
return head;
}
void printListNode(ListNode *head, void (*printFunc)(void *)){
if(!head){
printf("List is empty\n");
return;
}
ListNode *cur = head;
while(cur){
printFunc(cur->value);
cur=cur->next;
}
printf("\n");
}
void freeListNode(ListNode *head){
ListNode *cur = head;
ListNode *next=NULL;
while(cur){
ListNode *next= cur->next;
free(cur->value);
free(cur);
cur=next;
}
}
#endif
#ifdef TEST_LISTNODE_GENERIC
void printInt(void *value) {
printf("%d -> ", *(int *)value);
}
int main() {
ListNode *head = NULL;
// 添加节点到链表
int value1 = 10, value2 = 20, value3 = 30;
head = addListNode(head, &value1, sizeof(int));
head = addListNode(head, &value2, sizeof(int));
head = addListNode(head, &value3, sizeof(int));
// 打印链表
printf("原始链表: ");
printListNode(head, printInt);
// 删除值为20的节点
int valueToDelete = 20;
ListNode *node = delListNode(head, &valueToDelete, sizeof(int));
// 打印删除后的链表
printf("删除后的链表: ");
printListNode(head, printInt);
// 释放链表
freeListNode(head);
return 0;
}
#endif
#ifdef LISTNODE_INT
ListNode *newListNode(int value){
ListNode *node = malloc(sizeof(ListNode));
if(!node){
printf("Memory allocation failed\n");
exit(EXIT_FAILURE);
}
node->value = value;
node->next = NULL;
return node;
}
ListNode *addListNode(ListNode *head, int value){
ListNode *newNode = malloc(sizeof(ListNode));
if(!newNode){
printf("Memory allocation failed\n");
exit(EXIT_FAILURE);
}
newNode->value = value;
newNode->next = head;
head = newNode;
return head;
}
ListNode *delListNode(ListNode *head,int value){
ListNode *previous = NULL;
ListNode *current = head;
while(current!=NULL && current->value!=value){
previous = head;
current=current->next;
}
if (current==NULL){
printf("未找到相关值");
return head;
}
if(previous==NULL){
head = current->next;
}
else{
previous->next = current->next;
}
free(current);
return head;
}
void freeListNode(ListNode *head){
ListNode *temp;
while(head){
temp=head;
head = head->next;
free(temp);
}
free(head);
}
#endif
队列实现 #include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include "ListNode.h"
typedef struct LinkedListQueue{
ListNode *head;
ListNode *tail;
int queueSize;
} LinkedListQueue;
LinkedListQueue* newLinkedListQueue(){
LinkedListQueue *queue = malloc(sizeof(LinkedListQueue));
if(!queue){
printf("Memory allocation failed\n");
exit(EXIT_FAILURE);
}
queue->head = NULL;
queue->tail = NULL;
queue->queueSize = 0;
return queue;
}
void delLinkedListQueue(LinkedListQueue *queue){
ListNode * temp = queue->head;
while(temp){
ListNode *next = temp->next;
free(temp);
temp = next;
}
free(queue);
}
int size(LinkedListQueue *queue){
return queue->queueSize;
}
bool isEmpty(LinkedListQueue *queue){
return queue->queueSize == 0;
}
LinkedListQueue* enqueue(LinkedListQueue *queue, void *value,size_t elementSize){
ListNode *node = newListNode(value,elementSize);
if(queue->head==NULL){
queue->head=queue->tail=node;
}else{
queue->tail->next=node;
queue->tail=node;
}
queue->queueSize++;
return queue;
}
void* peek(LinkedListQueue *queue){
if(isEmpty(queue)){
printf("Queue is empty\n");
return NULL;
}
return queue->head->value;
}
void* deqeueu(LinkedListQueue *queue,size_t elementSize){
if(isEmpty(queue)){
printf("Queue is empty\n");
return NULL;
}
void* temp=peek(queue);
ListNode *tempNode = queue->head;
queue->head=queue->head->next;
free(tempNode);
queue->queueSize--;
return temp;
}
void printLinkedListQueue(LinkedListQueue* queue, void (*printFunc)(void*)){
if(isEmpty(queue)){
printf("Queue is empty\n");
return;
}
ListNode *temp = queue->head;
while(temp){
printFunc(temp->value);
temp = temp->next;
}
printf("\n");
}
#define TEST_LINKEDLISTQUEUE
#ifdef TEST_LINKEDLISTQUEUE
void printIntQueue(void *value){
printf("%d->",*(int*)value);
}
int main(){
LinkedListQueue *queue = newLinkedListQueue();
int a=1,b=3,c=5,d=7,e=9;
enqueue(queue,&a,sizeof(int));
enqueue(queue,&b,sizeof(int));
enqueue(queue,&c,sizeof(int));
enqueue(queue,&d,sizeof(int));
enqueue(queue,&e,sizeof(int));
printLinkedListQueue(queue,printIntQueue);
printf("Queue size: %d\n",size(queue));
printf("Queue is empty: %d\n",isEmpty(queue));
printf("Peek: %d\n",*(int*)peek(queue));
printf("Dequeue: %d\n",*(int*)deqeueu(queue,sizeof(int)));
printLinkedListQueue(queue,printIntQueue);
}
#endif |
Beta Was this translation helpful? Give feedback.
-
day04 |
Beta Was this translation helpful? Give feedback.
-
打卡 2025年6月12日 |
Beta Was this translation helpful? Give feedback.
-
发现一个问题,容易引起歧义。 |
Beta Was this translation helpful? Give feedback.
-
捉个虫,循环队列c语言中" queSize"的注释因该是队列长度吧,感觉写错了 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
chapter_stack_and_queue/queue/
一本动画图解、能运行、可提问的数据结构与算法入门书
https://www.hello-algo.com/chapter_stack_and_queue/queue/
Beta Was this translation helpful? Give feedback.
All reactions