【问题标题】:Problem with display function inside circular queue循环队列内的显示功能问题
【发布时间】:2022-01-12 23:17:49
【问题描述】:
#include <stdio.h>

# define MAX 3
int queue[MAX];  // array declaration
int front=-1;
int rear=-1;
// function to insert an element in a circular queue
void enqueue(int element)
{
    if(front==-1 && rear==-1)   // condition to check queue is empty
    {
        front=0;
        rear=0;
        queue[rear]=element;
    }
    else if((rear+1)%MAX==front)  // condition to check queue is full
    {
        printf("Queue is overflow..");
    }
    else
    {
        rear=(rear+1)%MAX;       // rear is incremented
        queue[rear]=element;     // assigning a value to the queue at the rear position.
    }
}

// function to delete the element from the queue
int dequeue()
{
    if((front==-1) && (rear==-1))  // condition to check queue is empty
    {
        printf("\nQueue is underflow..");
    }
 else if(front==rear)
{
   printf("\nThe dequeued element is %d", queue[front]);
   front=-1;
   rear=-1;
}
else
{
    printf("\nThe dequeued element is %d", queue[front]);
   front=(front+1)%MAX;
}
}
// function to display the elements of a queue
void display()
{
    int i=front;
    if(front==-1 && rear==-1)
    {
        printf("\n Queue is empty..");
    }
    else
    {
        printf("\nElements in a Queue are :");
        while(i<=rear)
        {
            printf("%d,", queue[i]);
            i=(i+1)%MAX;
        }
    }
}
int main()
{
    int choice=1,x;   // variables declaration

    while(choice<4 && choice!=0)   // while loop
    {
    printf("\nPress 1: Insert an element");
    printf("\nPress 2: Delete an element");
    printf("\nPress 3: Display the element");
    printf("\nEnter your choice");
    scanf("%d", &choice);

    switch(choice)
    {

        case 1:

        printf("Enter the element which is to be inserted");
        scanf("%d", &x);
        enqueue(x);
        break;
        case 2:
        dequeue();
        break;
        case 3:
        display();

    }}
    return 0;
}

我的显示功能有问题,如果后部在某些情况下可能小于前部,我如何打印所有元素,例如在这段代码中,我尝试将 3 个元素 1、2、3 排入队列,然后将两个元素出列,我的意思是这里 1, 2 之后我再次尝试对两个元素 1,2 进行排队,最后当我尝试显示元素时,我什么也没得到,所以显示队列元素的完美方式是什么

【问题讨论】:

  • 不相关:这个# define max 3 宏会造成无法估量的破坏。至少要大写 # define MAX 3 以避免意外将 std::max 之类的东西变成 std::3
  • @user4581301 完成
  • while(i&lt;=rear) 应该是do ... while(i != (rear+1)%MAX)
  • 对@Azrael3000 观点的进一步解释:因为循环缓冲区环绕它很容易在后备数组中拥有比front 更早的rear
  • 好吧,我只能推荐你使用调试器并单步执行代码,这是一项重要的学习技能,将来会对你有很大帮助

标签: c++ data-structures


【解决方案1】:

所以...这是一个可行的解决方案。

#include <stdio.h>

# define MAX 3

class CircularQueue
{

private:
    int queue[MAX];  // array declaration
    int front;
    int rear;

public:
    CircularQueue() :
        front(-1),
        rear(-1)
    { }

    // function to insert an element in a circular queue
    void enqueue(int element)
    {
        if(front==-1 && rear==-1)   // condition to check queue is empty
        {
            front=0;
            rear=0;
            queue[rear]=element;
        }
        else if((rear+1)%MAX==front)  // condition to check queue is full
        {
            printf("Queue is overflow..\n");
        }
        else
        {
            rear=(rear+1)%MAX;       // rear is incremented
            queue[rear]=element;     // assigning a value to the queue at the rear position.
        }
    }

    // function to delete the element from the queue
    void dequeue()
    {
        if((front==-1) && (rear==-1))  // condition to check queue is empty
        {
            printf("Queue is underflow..\n");
        }
        else if(front==rear)
        {
            printf("The dequeued element is %d\n", queue[front]);
            front=-1;
            rear=-1;
        }
        else
        {
            printf("The dequeued element is %d\n", queue[front]);
            front=(front+1)%MAX;
        }
    }

    // function to display the elements of a queue
    void display()
    {
        if(front==-1 && rear==-1)
            printf("Queue is empty..\n");
        else
        {
            printf("Elements in a Queue are: ");
            int i=front;
            do
            {
                if (i != front)
                    printf(",");
                printf("%d", queue[i]);
                i=(i+1)%MAX;
            } while (i != (rear+1)%MAX);
            printf("\n");
        }
    }
};

int main()
{
    CircularQueue cq;

    unsigned int choice=1;   // variables declaration

    while(choice<4 && choice!=0)   // while loop
    {
        printf("Press 1: Insert an element\n");
        printf("Press 2: Delete an element\n");
        printf("Press 3: Display the element\n");
        printf("Press any other number to exit\n");
        printf("Enter your choice: ");
        scanf("%d", &choice);

        switch(choice)
        {

        case 1:
            printf("Enter the element which is to be inserted: ");
            int x;
            scanf("%d", &x);
            cq.enqueue(x);
            break;
        case 2:
            cq.dequeue();
            break;
        case 3:
            cq.display();
        }
    }
    return 0;
}

我对输出进行了一些更改,请参阅\n 的位置。如果当前输出完成,给下一个打印语句写一个新行总是好的。

最大的变化,我把所有东西都放在了一个类中。这样你就没有任何全局变量,这对 99.999% 来说是一件坏事。您的代码非常类似于 C,因此通常我也会使用 std::cout,而使用 std::vector 您可以轻松地使缓冲区具有任意大小。

这是一些输出:

Press 1: Insert an element
Press 2: Delete an element
Press 3: Display the element
Press any other number to exit
Enter your choice: 1
Enter the element which is to be inserted: 2
Press 1: Insert an element
Press 2: Delete an element
Press 3: Display the element
Press any other number to exit
Enter your choice: 3
Elements in a Queue are: 2
Press 1: Insert an element
Press 2: Delete an element
Press 3: Display the element
Press any other number to exit
Enter your choice: 4

【讨论】:

    【解决方案2】:

    TL;DR 版本:制作循环缓冲区的难点在于从空条件中分辨出完整条件,因为它们都是 front == rear,除非您采取额外步骤,例如跟踪大小或维护 bool full; 或阻止 @ 987654323@从追赶到front

    我喜欢后一种方法,因为它可以编写非常简单的代码。我喜欢写简单的代码。您不必费力地调试它。您不必花费太多时间来编写它。您不会被支持它的维护团队打扰。简单的代码只有在太简单而遗漏了一个案例时才会成为问题。

    所以我在这里简单。

    在我认为合适的地方嵌入 cmets,因为当解释与解释的内容接近时,解释更容易理解。

    #include <stdio.h>
    
    
    // made MAX one bigger
    // If we waste a space in the queue the only time front can be the same as rear 
    // is if the queue is empty. No ambiguity. No special code for special cases or 
    // extra tracking variables to tell full from empty.
    // All for the low, low price of one queue element.
    # define MAX 4
    // in full on c++ this would be constexpr int MAX = 4;
    // In general avoid macros because they are really stupid. With a macro any 
    // token MAX will be replaced with 4 no matter how bad an idea it is. The 
    // resulting compiler errors get really weird.
    // with a constexpr, the compiler will not substitute anything and will take 
    // context into account, giving much better diagnostics if you screw up
    
    int queue[MAX]; // array declaration
                    // Don't comment the obvious stuff
                    // it just clutters up the code and makes you look... well..
                    // Hey, look! Dummy here needs a comment to rem'ber he's 
                    // defining an array! HA HA HA HA HA!
                    // You've got better things to do than put up with smurf like that.
    int front=0;
    int rear=0;
    // global variables suck. Because a global can be changed by anything at any 
    // time tracking errors is a pain in the neck. Every function could have 
    // unexpected side effects and needs to be examined while debugging.  
    
    // Plus because these variables are global and shared, you can only ever have 
    // ONE queue and EVERYBODY can use it.
    
    // These variables and the queue-handling functions should be in a queue class, 
    // and there should be an instance of this class defined in main.
    
    
    // helper functions to keep repetition down.
    // Also a well-named helper makes what's happening brutally obvious to anyone 
    // reading the code
    int advance(int pos)
    {
        return (pos+1)%MAX;
    }
    
    bool empty()
    {
        return front == rear;
    }
    
    bool full()
    {
        return front == advance(rear);
        // because of the wasted space telling full from empty is dead easy 
    }
    
    // function to insert an element in a circular queue
    void enqueue(int element)
    {
        if(full()) // see? Much easer to read than if (front == (rear+1)%MAX)
                   // now we barely need to comment.
        {
            printf("Queue is overflow.\n");
        }
        else
        {
            queue[rear]=element;     
            rear = advance(rear);
        }
    }
    
    // function to delete the element from the queue
    void dequeue()
    {
        if(empty())
        {
            printf("Queue is underflow.\n");
        }
        else
        {
            printf("The dequeued element is %d\n", queue[front]);
            front = advance(front);
        }
    }
    
    // function to display the elements of a queue
    void display()
    {
        if(empty())
        {
            printf("Queue is empty.");
        }
        else
        {
            int i = front;
            printf("Elements in a Queue are :");
            while(i!=rear)
            {
                printf("%d,", queue[i]);
                i = advance(i);
            }
        }
        printf("\n");
    }
    
    // test the logic in small chunks. Make sure the queue works perfectly before 
    // slapping in a menu system. If there's a bug, you don't have to ask if it's 
    // in the menu or in the queue because you're only testing one thing at a time
    // when you know they both work separately, put 'em together and test again 
    // just to be on the safe side.
    int main()
    {
        display();
        enqueue(1);
        display();
        dequeue();
        display();
        enqueue(2);
        display();
        enqueue(3);
        display();
        enqueue(4);
        display();
        enqueue(5); // fail
        display();
        enqueue(6); // fail
        display();
        dequeue();
        display();
        dequeue();
        display();
        dequeue();
        display();
        dequeue(); // fail
        display();
        dequeue(); // fail
        display();
    
       return 0;
    }
    

    【讨论】:

    • 不需要完整的标志。例如,您始终可以将前或后设置为 -1。
    猜你喜欢
    • 2011-04-02
    • 1970-01-01
    • 2020-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多