在C中使用数组实现队列

bvjveswy  于 2022-12-26  发布在  其他
关注(0)|答案(2)|浏览(111)

我想在C中实现一个队列。特别是我希望队列可以根据用户的喜好动态分配或固定大小。
我的问题是我不想每次弹出东西时都移动所有的值,所以我基本上跟踪了一个指针,该指针指示了数组中队列的开始和长度。当用户将队列设置为动态分配时,它增加了一些复杂性,使代码变得混乱。
我很好奇我是否能以某种方式释放动态分配内存的第一个元素,以及这是否会对我的代码产生奇怪的影响。
所以我想知道是否有人能告诉我:

  • 可以只释放使用malloc分配的内存的一部分?(我考虑在ptr+1和ptr上使用reallocarray,然后在原始指针上调用free,但这看起来像是ub,因为可能有一些关于操作系统内部存储的内存分配大小的信息)
  • 如果我继续以这种方式重新分配,我的数组是否会因为连续而“走出”进程内存?(我希望不会,因为我假设操作系统会进行一些智能Map,数组实际上并不是连续的,但最好能确定这一点)

因为即使我发现我的问题相当混乱的公式所附的图表说明以上两点:

nukf8bse

nukf8bse1#

memmove可用于移位元件。
这将保留分配的内存,直到程序终止。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define INC 50

typedef struct queue_s queue;
struct queue_s {
    size_t size;
    size_t used;
    int *arr;
};

queue pop ( queue q) {
    if ( q.used) {
        q.used -= 1;
        memmove ( &q.arr[0], &q.arr[1], sizeof *q.arr * q.used);
    }
    else {
        printf ( "queue is empty\n");
    }
    return q;
}

queue push ( int data, queue q) {
    int *temp = NULL;

    if ( q.used >= q.size) {
        if ( NULL == ( temp = realloc ( q.arr, sizeof *temp * (q.size + INC)))) {
            fprintf ( stderr, "problem realloc q.arr");
            return q;
        }
        q.arr = temp;
        q.size += INC;
    }
    q.arr[q.used] = data;
    q.used += 1;
    return q;
}

void show ( queue q) {
    if ( q.used) {
        for ( size_t each = 0; each < q.used; ++each) {
            if ( each) {
                printf ( "->%d", q.arr[each]);
            }
            else {
                printf ( "%d", q.arr[each]);
            }
        }
    }
    else {
        printf ( "nothing to show\n");
    }
    printf ( "\n");
}

int main ( void) {
    queue qu = { 0, 0, NULL};

    qu = push ( 0, qu);
    qu = push ( 1, qu);
    qu = push ( 2, qu);
    qu = push ( 3, qu);
    qu = push ( 4, qu);
    qu = push ( 5, qu);
    qu = push ( 6, qu);
    qu = push ( 7, qu);
    qu = push ( 8, qu);
    qu = push ( 9, qu);

    for ( int each = 0; each < 100000; ++each) {
        qu = push ( each, qu);
    }
    printf ( "pushed\n");
    for ( int each = 0; each < 100000; ++each) {
        qu = pop ( qu);
    }
    printf ( "popped\n");

    show ( qu);
    qu = pop ( qu);
    show ( qu);
    qu = push ( 10, qu);
    show ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    show ( qu);
    qu = push ( 11, qu);
    qu = push ( 12, qu);
    show ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    show ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    qu = pop ( qu);
    show ( qu);

    free ( qu.arr);

    return 0;
}
8e2ybdfx

8e2ybdfx2#

1.是的,使用malloc可以只释放一部分内存,你可以使用realloc()函数来调整分配的内存大小,然后在原始指针上调用free()
1.不,你的数组不会“走”出进程内存。操作系统会进行智能内存Map,防止这种情况发生。

#include<stdio.h>  
#include<stdlib.h>

// A structure to represent a queue  
struct Queue {   
  int front, rear, size;
  unsigned capacity;  
  int* array;  };    
// function to create a queue of given capacity.  
// It initializes size of queue as 0  
struct Queue* createQueue(unsigned capacity)  {   
    struct Queue* queue = (struct Queue*) malloc(sizeof(struct Queue));             
    queue->capacity = capacity;   queue->front = queue->size = 0;     
    queue->rear = capacity - 1; // This is important, see the enqueue    
    queue->array = (int*) malloc(queue->capacity * sizeof(int));   
    return queue;  
}    
// Queue is full when size becomes equal to the capacity  
int isFull(struct Queue* queue)  { 
    return (queue->size == queue->capacity); 
}    

// Queue is empty when size is 0  
int isEmpty(struct Queue* queue)  { 
    return (queue->size == 0); 
}    

// Function to add an item to the queue.  
// It changes rear and size  
void enqueue(struct Queue* queue, int item)  {   
    if (isFull(queue))   return;   queue->rear = (queue->rear + % queue->capacity;
    queue->array[queue->rear] = item;   queue->size = queue->size + 1;      
    printf(&quot;%d enqueued to queue\n&quot;, item);  
}    

// Function to remove an item from queue.  
// It changes front and size  
int dequeue(struct Queue* queue)  {   
    if (isEmpty(queue))   return INT_MIN;
    int item = queue->array[queue->front];   
    queue->front = (queue->front + 1)%queue->capacity;
    queue->size = queue->size - 1;   
    return item;  
}    

// Function to get front of queue  
int front(struct Queue* queue)  {
    if (isEmpty(queue))   return INT_MIN;
    return queue->array[queue->front];  
}    

// Function to get rear of queue  
int rear(struct Queue* queue)  {   
    if (isEmpty(queue))   return INT_MIN;   
    return queue->array[queue->rear];  
}    

// Driver program to test above functions./  
int main()  {   
    struct Queue* queue = createQueue(1000); 
    enqueue(queue, 10);   
    enqueue(queue, 20); 
    enqueue(queue, 30);
    enqueue(queue, 40);
    printf(&quot;%d dequeued from queue\n\n;, dequeue(queue));
    printf(&quot;Front item is %d\n;, front(queue));
    printf(&quot;Rear item is %d\n&quot;, rear(queue));
    return 0;  
}

相关问题