Я изучаю циклическую очередь в структуре данных. Как видно из приведенного ниже кода, я пытаюсь удалить определенные данные и вставить данные в циклическую очередь. Однако, когда я пытаюсь запустить его, возникает проблема при удалении данных и вставке новых. Я понятия не имел об этом. Я пытался решить эту проблему в течение многих часов, но ничего не нашел. Любая помощь будет оценена по достоинству.
#include <stdio.h>
#define SIZE 3
typedef struct queue{
int val[SIZE] = {NULL};
int front;
int rear;
}queue;
void display(struct queue *q);
void enqueue(struct queue *q){
int ins,i=1;
if ((q->rear == SIZE-1 && q->front == 0) || (q->rear == q->front-1)){
printf("Queue is full!\n");
}
else if (q->front == -1)
{
printf("Enqueue data : ");
scanf("%d",&ins);
q->front = q->rear = 0;
q->val[q->rear] = ins;
}
else if (q->rear == SIZE-1)
{
printf("Enqueue data : ");
scanf("%d",&ins);
q->rear = 0;
q->val[q->rear] = ins;
}
else
{
printf("Enqueue data : ");
scanf("%d",&ins);
q->rear++;
q->val[q->rear] = ins;
}
display(q);
};
void dequeue(struct queue *q);
int main(){
queue *q= new queue;
q->front = -1;
q->rear = -1;
char select;
flag1:
printf("\n------- Please Select Operations ---------\n");
printf("Press e: Enqueue\n");
printf("Press d: Dequeue\n");
printf("Press x: Exit Program\n");
printf("------------------------------------------\n");
printf("Select Menu : ");
scanf(" %c",&select);
switch(select){
case 'e' : enqueue(q); goto flag1;
case 'd' : dequeue(q); goto flag1;
case 'x' : break;
}
return 0;
}
void dequeue(struct queue *q){
int deq,hold;
if (q->front == -1)
{
printf("Queue is Empty");
}
else
{
printf("Dequeue data : ");
scanf("%d",&deq);
for(int i=0;i<SIZE;i++){
if (deq==q->val[i]){
if (i==q->front){
q->val[q->front]=NULL;
q->front = i;
q->rear=q->rear+1;
if (q->rear=SIZE-1){
q->rear=0;
}
}
else
q->val[q->front]=NULL;
}
}
display(q);
}
};
void display(struct queue *q){
int i;
printf("Queue : |");
for (i= 0; i<SIZE; i++){
if (q->val[i]==NULL){
printf(" |");
}
else
printf("%d|", q->val[i]);
}
};
Ваш вопрос помечен c
, а ваш код — 99,44% c
. Но вы делаете new queue
, что есть c++
. Если бы вы изменили это на: queue *q = malloc(sizeof(*q));
было бы 100% c
У вас есть int val[SIZE] = { NULL };
Это было бы c++
, если бы вы использовали 0
[vs. NULL
]. Итак, вы хотите, чтобы val
было int
или int *
? В dequeue
вы делаете: q->val[q->front] = NULL;
, значит, val
есть int *
. Но в enqueue
вы делаете: q->val[q->rear] = ins;
где ins
— это int
. Итак, это конфликт, когда [в структуре queue
] val
должен быть как int
, так и int *
. Я предполагаю, что вы хотите int val[SIZE];
, но когда вы удаляете, какое значение вы хотите для дозорного, указывающего на «пустую» ячейку?
Как правило, смысл круговых очередей заключается в том, чтобы работать исключительно с передней и задней частью (задняя часть для вставки, передняя часть для извлечения). Ваша функция удаления - это удаление по значению, а не просто удаление переднего значения. Похоже, у него много проблем: 1) произвольный доступ вместо доступа только к началу, 2) предположение, что очередь пуста только тогда, когда front == -1
(что никогда не верно после первой вставки), 3) проверка, если i == q->front
затем установка q->front = i
, 4) обновление q->rear
во время удаления из очереди вместо увеличения q->front
, 5) установка q->rear=SIZE-1
в условии if.
Есть и другие проблемы, но у меня закончились персонажи. В дополнение к замечаниям Крейга я бы предложил пересмотреть свое понимание очередей и того, как обычно работают их операции. Если вам нужен произвольный доступ, просто используйте массив. Если вам нужна очередь, удаление из очереди должно работать только с передним адресом, а не выполнять поиск по значению.
@Welbog Я рад, что ты упомянул об этом. Я не был уверен, означает ли «круговая очередь» «кольцевую очередь». То есть пустым является q->front == q->rear
[с переносом индексов на SIZE
]. Для меня «круговой» означает двусвязный список, где tail->next == head
и head->prev == tail
вместо NULL
@CraigEstey, может быть и так. Из реализации enqueue мне кажется, что это кольцевая очередь.
@CraigEstey Спасибо за комментарии. О int val[SIZE] = {NULL} Я хочу, чтобы int был int, а не int*, поэтому мне интересно, можно ли изменить {NULL} на 0, а также изменить условие в очереди.
ГИГО!
Ваш код слишком сложный.
Сложный код требует сложного тестирования и отладки.
Попробуйте следующий код:
void enqueue( struct queue *q, int v) {
int r = (q.rear + 1) % SIZE
if (( r == q.front) {
printf( "Queue is full!\n");
} else {
q.val[ q.rear] = v;
q.rear = r;
}
};
int dequeue( struct queue *q) {
if ( q.front == q.rear) {
printf( "Queue is Empty");
v = NULL; # or whatever (required as a return value)
} else {
v = q.val[ q.front];
q.front = ( q.front + 1) % SIZE;
}
return v;
};
int main() {
queue *q = new queue;
q->front = q->rear = 0;
...
};
Обобщить:
Обратите внимание, что этот простой алгоритм всегда оставляет неиспользуемый элемент в буфере. Это необходимо для того, чтобы отличить «полный» от «пустой».
@"Max P Apth" Я не знаю, какой компилятор вы используете. Но я предполагаю, что это C++ с некоторой совместимостью с C. Эта программа не тестировалась, но она должна работать.
Ваш код чрезмерно и тупо сложен. Я думаю, вы плохо понимаете круговые очереди.
Вот мой упрощенный код. Вы можете проверить это и узнать что-то.
#include<stdio.h>
#include<stdlib.h>
typedef struct _node {
int size,front,rear,*q;
} node;
node *pu;
void initialize() {
if (pu!=NULL)
free(pu);
pu = (node *)malloc(sizeof(node));
printf("\nEnter the size of the queue :- ");
scanf(" %d",&pu->size);
pu->q = (int *)malloc(sizeof(int) * pu->size +1);
pu->front = pu->rear = 0;
}
int isempty() {
return (pu->front == pu->rear);
}
int isfull() {
return ((pu->rear + 1) % pu->size == pu->front);
}
void enqueue(int x) {
if (isfull())
return;
else {
pu->q[pu->rear=(pu->rear +1) % pu->size] = x;
}
}
int dequeue() {
if (isempty())
return '$';
else {
return pu->q[ pu->front = (pu->front + 1) % pu->size];
}
}
void display() {
if (isempty())
return;
else {
for( int i = pu->front + 1; i != (pu->rear +1)%pu->size ; i = ( i +1) % pu->size)
printf("\n %d",pu->q[i]);
}
}
int main() {
// do something in here with the functions.
return 0;
}
-1: этот код правильный, но очень непрозрачный. Маловероятно, что кто-то, кто плохо знаком с C или циклическими буферами, может понять это. Преамбула излишне груба.
@Welbog на самом деле код для начинающих. мой профессор дал мне написать это с минимальным количеством символов, поэтому я написал это.
Циклическая очередь в Java
public class CircularQueue<T> {
private Object[] arr;
private int front = -1, rear = -1;
public CircularQueue(int initialCapacity) {
this.arr = new Object[initialCapacity];
}
public void add(T val) throws Exception {
if (isEmpty()) {
rear++;
front++;
} else if (isFull()) {
throw new Exception("Queue is full");
}
arr[rear] = val;
rear = (rear + 1) % arr.length;
}
public T delete() throws Exception {
if (isEmpty()) {
throw new Exception("No elements in Queue");
}
T temp = (T) arr[front];
front = (front + 1) % arr.length;
return temp;
}
public boolean isEmpty() {
return (front == -1 && rear == -1);
}
public boolean isFull() {
return (front == rear);
}
@Override
public String toString() {
String ret = "[ ";
int temp = front;
do {
ret += arr[temp] + " ";
temp = (temp + 1) % arr.length;
} while (temp != rear);
ret += "]";
return ret;
}
}
«Я пытался решить эту проблему в течение многих часов, но ничего не нашел». - так что пошаговое выполнение этого с помощью отладчика и заметка о конкретных значениях переднего и заднего индексов при этом ничего не дало вам?