【问题标题】:Resizing of the circular queue using dynamic array使用动态数组调整循环队列的大小
【发布时间】:2019-08-16 00:59:51
【问题描述】:

下面的代码我分析了很久,还是没有得到这个函数的一行,如下:

void ResizeQueue(struct DynArrayQueue* q) {
    int size = q->capacity;
    q->capactiy = q->capacity * 2;
    q->array = realloc(q->array, q->capacity);
    if (!q->array) {
        printf("Memory error");
        return;
    }

    // The doubt lines:
    if (q->front > q->rear) {
        for (int i = 0; i < q->front; i++) {
            q->array[i + size] = q->array[i];
        }
        q->rear = q->rear + size;
    }
}

我对上面这段代码的疑问是,在这个循环队列的动态数组实现中,在什么时候,前面变得比后面更大?

【问题讨论】:

    标签: c arrays queue dynamic-arrays


    【解决方案1】:

    原因是因为它是一个循环缓冲区。假设一个缓冲区长度为8,这里有两个场景A和B,其中4个数据项在缓冲区中,-表示无关数据,d表示缓冲数据:

    index   0   1   2   3   4   5   6   7
    
    A data  -   d   d   d   d   -   -   -
              begin        end
    
    B data  d   d   -   -   -   -   d   d
               end                begin
    

    所以因为 - 根据循环缓冲区的定义 - 数据回绕,头部可能低于尾部,或者尾部可能低于头部。

    看看当缓冲区 B 的长度加倍时会发生什么

    index   0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15
    B data  d   d   -   -   -   -   d   d   -   -   -   -   -   -   -   -
               end                begin
    

    现在应该很清楚为什么需要移动数据,如下所示:

    index   0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15
    B data  d   d   -   -   -   -   -   -   -   -   -   -   -   -   d   d
               end                                                begin
    

    相应调整指针或索引。

    或者,可以将数据调整为如下所示:

    index   0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15
    B data  -   -   -   -   -   -   d   d   d   d   -   -   -   -   -   -
                                  begin        end
    

    【讨论】:

    • 解释得很好,明白了,非常感谢!
    • 我认为您的最后一张图不正确 - 代码将“begin = front”保留在 6 处,并将数据从 0..5 移动到 8..13
    • @AShelly 答案的最后一行说“相应调整了指针或索引。”
    • 好的,但是在 OP 的代码中,移动循环是 for(int i = 0 ; i&lt;q-&gt;front ; i++) - 第一部分,而不是 for (i=q-&lt;front;i&lt;size;i++),它将移动第二部分。我想一个有效的实现会选择这两者中的任何一个范围更小
    • @AShelly 编辑现在显示缓冲区的相同部分作为 OP 的代码移动:有两种方法可以调整它。
    【解决方案2】:

    所以“前面”是读指针,下一个要读的东西。 “后”是写指针,最后插入的东西。

    任何时候循环队列中插入的元素超过capacityrear 会绕到开头,front &gt; rear 变为真。这种机制使它成为一个循环缓冲区。

    如果在此之后调用此调整大小代码,它会将front 读取指针之前的所有内容复制到最后的新空间中,并更新rear 以指向该空间。

    (我认为如果它只复制元素到rear 也是正确的。正如所写的那样,它正在复制陈旧的元素。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-17
      • 1970-01-01
      • 1970-01-01
      • 2012-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多