繁体   English   中英

Java数组表示队列数据结构

[英]Java Array representation of queue data structure

我试图通过用一维数组表示它来建立队列。 我知道人们可能会建议我通过使用列表甚至是默认的java队列对象来获得更轻松的时间,但我在这里学习,所以我不想求助于这样简单的解决方案。 到目前为止,我遇到了一些问题:

  1. 如果队列是完整对象,则无法添加。
  2. 移动物体。

例如QueueArray - > [],[A],[B]将它移动以使它最终结束:QueueArray - > [A],[B],[]

现在听我说,问题1#。 我的逻辑思维告诉我以某种方式增加队列数组的大小以便能够接收更多的对象,事情是我不知道怎么做而不将所有对象保存到另一个临时数组然后将它们复制到一个新的数组更大的数组。 我甚至不确定这是否是一种合理可行的方法来实现这一目标。

问题2#我想可能只是检查队列数组中的空对象,如果找到它们,只需将元素移动一个索引即可。

这是我的代码,我也对其他改进持开放态度。

import java.util.Scanner;

public class Queue {
    Object[] q;
    int head, tail;
    Scanner in;

    public Queue(int size){ 
        q = new Object[size];
        menu();
    }

    public void menu(){
        System.out.println("\t");   
        System.out.println("1. add(x) - Adds the object x to end of the queue");
        System.out.println("2. remove() - Removes the first object in the queue");
        System.out.println("3. view - Shows contents in queue");
        System.out.println("4. exit - Exits program");
        System.out.println("Select your operation:"+"\t");  

        while(true){
            in = new Scanner(System.in);
            int userInput = in.nextInt();

            if(userInput == 1){
                System.out.println("Give value of object");
                in = new Scanner(System.in);
                Object userIn = in.next();
                add(userIn);
                menu();
            }

            if(userInput == 2){
                remove();
                menu();
            }

            if(userInput == 3){
                peek();
                menu();
            }

            if(userInput == 4){
                System.exit(0);
            }
        }
    }

    // Adds the object to the end of the queue
    Object add(Object letter){

        // If the queue is not full, add to back of queue
        if(tail >= q.length){
            System.out.println("Queue is full");
            return null;
        } else {
            q[tail] = letter;
            tail++;
        }
        return tail;
    }

    // Removes the first object in the queue
    Object remove(){
        if(q.length == 0){
            return null;
        } else {
            q[head] = null;
            head++;
        }
        return head;
    }

    // Returns the head, tail and all other objects in the queue
    void peek(){
        System.out.println("Head: "+q[head]);
        System.out.println("Tail: "+q[tail-1]);
        System.out.println(q[0]+", "+q[1]+", "+q[2]+", "+q[3]+", "+q[4]+".");
    }

    public static void main(String[] args){
        new Queue(5);
    }
}

在内部,我相信大多数Java列表对象在某些时候实际上只有一个不可变数组,这正是你遇到的。

他们做什么来调整大小,然后达到一个完整的%阈值(比如说75%),他们将创建一个大小翻倍的新数组。 因此,如果您有一个4项数组,并插入了三个项目,该结构将在内部将其存储阵列更新为大小为8,并在有6个项目等时再次执行此操作。

至于执行实际复制,请查看System.arraycopy,它允许您指定源和目标数组。

在转移方面,为何转变? 为什么不保持指向当前索引的指针?

例如,看看这个操作链......

队列对象,队列对象,出列对象,队列对象。

您的结构可能看起来像

[,,,] - head at 0, tail at 0
[obj1,,,] - head at 0, tail at 1
[obj1,obj2,,] - head at 0, tail at 1
[obj1,obj2,,] - head at 1, tail at 1
[obj1,obj2,obj3,] - head at 1, tail at 2
[obj1,obj2,obj3,] - head at 2, tail at 2

使用此方法,并且如其他答案所述,您还可以包装索引以查找仍可用的元素。 在上面的示例中,如果您添加了两个元素,因为前两个元素已不再使用,您可以开始用新元素替换它们。

显然,当足够的对象没有出列以允许更多的队列排队时,你仍然需要处理调整大小。

所以,你是正确的,有数据结构完全符合你的要求,但由于这更像是一个练习而不是应用程序,这就是我所说的。

#1

您将整个n长度数组复制到n + 1长度数组的解决方案是可行的。 但是还有另外两种方法可以执行此操作,这两种方法通常都使用,这两种方法都不涉及复制整个数组。

第一种是在创建队列时预先分配最大大小。 这与您在C中为数组预先分配内存的方式类似。 这是迄今为止最简单的3种解决方案,而且速度最快。

我要指出,如果你使用这个解决方案,你会经常看到用于实现队列的所谓“循环缓冲区”或“环形缓冲区”[1]。 您应该阅读有关此主题的链接文章。

第二种是使用某种链表[2],而不是仅存储值,而是存储(值,下一地址)对。 然后,您可以动态添加项目。 但是用Java做这件事非常困难。 链接的文章提供了有关链接列表的更多信息。

#2

不要转移。 根据队列的大小和元素的大小,可能需要更长的时间 - 移位将是O (n) - 如果您不知道这意味着什么,请参阅[3]。

而不是移动,使用像循环缓冲区[1]。 跟踪头部和尾部(或头部和大小)。

如果你使用环形缓冲区执行这样的操作,那么插入将是O (1) - 好多了。

在旁边

在我看来,了解数据结构非常重要,所以很好。 但是(同样,我的观点)像Java这样的语言使得理解数据结构的基础知识比比如C或C ++更难。 请注意,并非不可能,但Java的托管内存方面混淆了C不具备的一些更精细的数据结构实现点。 如果你真的想要理解这些数据结构,我强烈建议在某些时候用C / C ++实现它们,只是为了看看它是什么以及它是如何工作的。

[1] http://en.wikipedia.org/wiki/Circular_buffer
[2] http://en.wikipedia.org/wiki/Linked_list
[3] http://en.wikipedia.org/wiki/Big_O_notation

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM