简体   繁体   English

Java的。 如何将两个最初排序的队列合并到一个队列中? (没有链接列表或其他内容)

[英]Java. How to merge two initially sorted queues in one queue? (without linked lists or something else)

For example I have first queue: front[1 3 5 7]back and second queue front[2 4 6 8]back. 例如,我有第一个队列:front [1 3 5 7] back和第二个队列front [2 4 6 8] back。 New merged queue must be: front[1 2 3 4 5 6 7 8]back. 新的合并队列必须为:front [1 2 3 4 5 6 7 8] back。 Or first queue: front[1 3 3 7]back, second: front[2 4 5 7 8]back. 或第一个队列:front [1 3 3 7] back,第二个队列:front [2 4 5 7 8] back。 New merged queue: front[1 2 3 3 4 5 7 7 8]back. 新的合并队列:front [1 2 3 3 4 5 7 7 8] back。 And we can't use any types of sorting. 而且我们不能使用任何类型的排序。 Here is the my implementation of queue: 这是我对队列的实现:

public class QueueImpl implements IntQueue {

    protected int capacity;
    public static final int CAPACITY = 100;
    protected int Q[];
    protected int f = 0, r = 0;

    public QueueImpl() {
        this(CAPACITY);
    }

    public QueueImpl(int cap) {
        capacity = cap;
        Q = new int[capacity];
    }


    public void enqueue(int value) throws Exception {
        if (getSize() == capacity - 1) {
            throw new Exception("Full"); //To change body of generated methods, choose Tools | Templates.
        }

        Q[r] = value;

        r = (r + 1) % capacity;

    }


    public int dequeue() throws Exception {
        int element;
        if (isEmpty()) {
            throw new Exception("Empty"); //To change body of generated methods, choose Tools | Templates.
        }
        element = Q[f];

        f = (f + 1) % capacity;
        return element;

    }


    public int getSize() {
        return (capacity - f + r) % capacity;
    }


    public boolean isEmpty() {
        return (f == r);
    }

    public String toString() {
        int z = f;
        String s;
        s = "f[";

        if (getSize() >= 1) {
            s += Q[0];
            for (int i = 1; i <= getSize() - 1; i++) {
                s += " " + Q[z + 1];
                z = (z + 1) % capacity;

            }
        }
        return s + "]b";
    }

}

My solution: public class Assign2Problem3Solution { 我的解决方案:公共类Assign2Problem3Solution {

public static IntQueue merge(IntQueue q1, IntQueue q2) throws Exception {
    IntQueue merged = new QueueImpl();
    int a, b, k, t, m;




    if (a < b) {
        k = a;
        t = b - a;
    } else {
        k = b;
        t = a - b;
    }

    for (int i = 0; i < k; i++) {

        a = q1.dequeue();
        b = q2.dequeue();
        if (a < b) {
            merged.enqueue(a);
            merged.enqueue(b);
        } else if (b < a) {
            merged.enqueue(b);
            merged.enqueue(a);
        }

    }
    if (q1.getSize() > q2.getSize()) {

        for (int i = 0; i < t; i++) {
            m = q1.dequeue();
            merged.enqueue(m);

        }
    } else if (q1.getSize() < q2.getSize()) {
        for (int i = 0; i < t; i++) {
            m = q2.dequeue();
            merged.enqueue(m);

        }
    }

    return merged;
}

} }

Here is the code that works and satisfies the conditions: 这是可以运行并满足条件的代码:

IntQueue merged = new QueueImpl(); IntQueue合并= new QueueImpl(); int a, b; 整数a,b;

    if (!q1.isEmpty() && !q2.isEmpty()) {
        a = q1.dequeue();
        b = q2.dequeue();
        while (true) {
            if (a < b) {
                merged.enqueue(a);
                if (q1.isEmpty()) {
                    merged.enqueue(b);
                    break;
                }
                a = q1.dequeue();
            } else {
                merged.enqueue(b);
                if (q2.isEmpty()) {
                    merged.enqueue(a);
                    break;
                }
                b = q2.dequeue();
            }
        }
    }
    if (q1.getSize() > 0) {
        while (!q1.isEmpty()) {
            a = q1.dequeue();
            merged.enqueue(a);
        }
    } else if (q2.getSize() > 0) {
        while (!q2.isEmpty()) {
            b = q2.dequeue();
            merged.enqueue(b);
        }
    } 

    return merged;

The problem is here: 问题在这里:

    a = q1.dequeue();
    b = q2.dequeue();
    if (a < b) {
        merged.enqueue(a);
        merged.enqueue(b);
    } else if (b < a) {
        merged.enqueue(b);
        merged.enqueue(a);
    }

This code means remove one element from the first queue, and remove one element from the second queue. 此代码意味着从第一个队列中删除一个元素,并从第二个队列中删除一个元素。 Add the smaller element into the merged queue, and then add the larger element into the merged queue. 将较小的元素添加到合并队列中,然后将较大的元素添加到合并队列中。

The above code does not work for some cases. 上面的代码在某些情况下不起作用。 One example is this. 一个例子就是这个。 Consider two queues Q1 = {1, 2, 3} and Q2 = {4, 5, 6}. 考虑两个队列Q1 = {1,2,3}和Q2 = {4,5,6}。 In step 1 (loop, k = 0), we remove 1 from Q1 and 4 from Q2. 在第1步(循环,k = 0)中,我们从Q1中删除1,从Q2中删除4。 Because 1 is smaller than 4, we add 1, followed by 4. The merged queue is {1, 4}, Q1 is now {2, 3}, and Q2 is now {5, 6}. 因为1小于4,所以我们加1,后跟4。合并的队列为{1,4},Q1现在为{2,3},Q2现在为{5,6}。 In step 2 (loop, k = 1), we remove 2 from Q1 and 5 from Q2. 在第2步(循环,k = 1)中,我们从Q1中删除2,从Q2中删除5。 Because 2 is smaller than 5, we add 2, followed by 5. The merged queue is now {1, 4, 2, 5}. 因为2小于5,所以我们加2,后跟5。合并后的队列现在为{1、4、2、5}。 Notice that although 2 is smaller than 4, we add 2 after 4, which is incorrect. 请注意,尽管2小于4,我们在4之后加2,这是不正确的。 The problem here is that in step 1, we cannot immediately add 4, because the next element in Q1 (which is 2) may be smaller than 4. 这里的问题是,在步骤1中,我们无法立即添加4,因为Q1中的下一个元素(即2)可能小于4。

What you need to do is something like this: 您需要做的是这样的:

int e1 = q1.dequeue();
int e2 = q2.dequeue();

while (true) {
  if (e1 < e2) {
    merged.enqueue(e1);
    if (q1.isEmpty()) {
      // add remaining q2 elements
      while (!q2.isEmpty()) { 
        merged.enqueue(q2.dequeue());
      }
      break;
    }
    // take another element from q1
    e1 = q1.dequeue();
  } else {
    merged.enqueue(e2);
    if (q2.isEmpty()) {
      // add remaining q1 elements
      while (!q1.isEmpty()) { 
        merged.enqueue(q1.dequeue());
      }
      break;
    }
    // take another element from q2
    e2 = q2.dequeue();
  }
}

If you have a method that can retrieve the head element, without removing it from the queue, the code can be much cleaner. 如果您有一种方法可以检索head元素,而无需将其从队列中删除,则代码可以更加简洁。

Implement the peek() method, and compare the values as they are peeked to see which on is smaller and start adding them into a new queue. 实现peek()方法,并比较它们的值,以查看哪个较小,然后开始将它们添加到新队列中。

Pretty much the merge part of a "MergeSort" 几乎是“ MergeSort”的合并部分

You could simply do the following : 您可以简单地执行以下操作:

C = new queue
a = A.poll() 
b = B.poll()
While A or B is NOT EMPTY
    while( b < a ) 
        - C.put(b)
        - b = B.Poll()
    - C.put(a)
    - a = A.poll()
FILL C with the queue left 

It is just alterning between both list taking each time the number closest to the last number in C.At the end, you just fill the last number from the queue that is not empty. 这只是在两个列表之间进行更改,每次获取最接近C中最后一个数字的数字。最后,您只需填充队列中不为空的最后一个数字。

You got to pay attention to empty list, here it s just a really simple pseudo code, but when i do "b = B.Poll()" i should pay attention whether there is still an element in B or not, otherwise it might throw an exception. 您必须注意空列表,这只是一个非常简单的伪代码,但是当我执行“ b = B.Poll()”时,我应注意是否在B中仍然存在一个元素,否则可能会引发异常。

Well, i've just tried this on a simple example, i do not say it is working 100% but it gives you ideas. 好吧,我只是在一个简单的例子上试过了,我不说它正在100%工作,但是它给了您一些想法。 Ps: here my "poll" => "dequeue" for your class 附言:这里是我的“投票” =>“出队”

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

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