排序算法 - java排序堆栈

时间:2015-12-08 05:08:55

标签: algorithm sorting stack queue

这是我提出的:

procedure sort(Stack S, Queue Q, sortedPosition)
    if(sortedPosition==0)
        // Sorting completed
        return;

    max = S.pop
    currentPosition = 0;

    while (!S.isEmpty()) do:
        currentPosition = currentPosition + 1;
        if(currentPosition < sortedPosition)
            current = S.pop();
            if(current > max)
                Q.add(max);
                max = current;
            else
                Q.add(current);
            end if
        end if

    end while

    S.push(max);
    currentPosition--;

    while (!Q.isEmpty()) do:
        S.push(Q.remove());
    end while


    sort(S, Q, currentPosition);
end procedure

有人可以看看并告诉我,如果我做错了吗?此外,最坏情况下的运行时间必须为O(n ^ 2)。

3 个答案:

答案 0 :(得分:2)

可以使用队列和堆栈实现自下而上的合并排序O(n log(n))。首先,所有元素都从堆栈弹出到队列中(这会反转元素)。队列将反向排序(反转比较的意义)。第一个合并传递从队列中弹出一个元素并将其推送到堆栈,将queue.front()与stack.top()进行比较,弹出并将较小的推入队列,然后弹出并推送另一个,重复直到所有元素对合并,在队列中创建大小为2的排序运行。然后为了设置下一次传递,队列被循环以反转所有偶数运行(除非有一个单独的甚至在最后运行而没有奇数运行合并,在这种情况下它被复制而不是反转):甚至从队列中运行被推入堆栈,然后从堆栈弹出并推入队列以反转它们,奇怪的运行从队列中弹出并推入队列以按顺序复制它们。对于剩余的传递,通过从队列中弹出偶数运行并将其推入堆栈来合并运行对,&#34; unversing&#34;它在堆栈上,然后在stack.top()的偶数运行与queue.front()中的奇数运行合并,将合并的运行推回队列。合并所有对后,运行大小加倍,如果运行大小&lt; queue.size(),然后再次循环队列以反转所有偶数运行并重复合并过程; else run size&gt; = queue.size()和队列排序(反向)。弹出反向排序队列并将其推入堆栈,创建一个已排序的堆栈。

我试图找出一种方法来在合并过程中扭转比较的意义,以避免在每次合并传递后不得不进行反向甚至运行周期,但它是一种递归模式,我无法做到这一点。弄清楚如何使用迭代进行复制。无论如何,更简单的反向均匀运行方法似乎足够快。

在我的系统上,英特尔2600K 3.4 ghz,Visual Studio发布版本,这种方法可以在大约2.8秒内对400万个伪随机32位无符号整数进行排序。

用于递增堆栈排序的示例代码(用于降序的反向比较)。 ll,rr和ee是伪索引,用于使运行计数逻辑与数组/向量自底向上合并排序保持一致。实际的合并使用堆栈用于左/偶运行,以及一部分队列用于右/奇运行。

typedef unsigned int uint32_t;

void sqsort(std::stack <uint32_t> &s , std::queue <uint32_t> &q)
{
    size_t n = s.size();
    while(!s.empty()){                      // pop/push s to q
        q.push(s.top());
        s.pop();
    }
    // merge sort usign stack and queue
    size_t r = 1;
    while(1){
        size_t ee = 0;                      // pseudo end index
        // merge pass
        while(ee < n){
            size_t ll = ee;                 // ll = pseudo start of left  run
            size_t rr = ll+r;               // rr = pseudo start of right run
            if(rr >= n){                    // if only left run
                while(ll++ < n){            //   copy it and break
                    q.push(q.front());
                    q.pop();
                }
                break;
            }
            ee = rr+r;                      // ee = pseudo end of right run
            if(ee > n)
                ee = n;
            // merge a pair of runs
            // stack == left / even run
            // queue == right / odd run
            size_t m = rr - ll;             // m = # elements in left run
            while(m--){                     //  pop/push left run to stack
                s.push(q.front());
                q.pop();
            }
            m = ee - rr;                    // m = # elements in right run
            while(1){
                if(q.front() > s.top()){    // (reverse for descending)
                    q.push(q.front());
                    q.pop();
                    if(--m == 0){           // if end right run
                        while(!s.empty()){  //   copy rest of left run
                            q.push(s.top());
                            s.pop();
                        }
                        break;              //   and break
                    }
                } else {
                    q.push(s.top());
                    s.pop();
                    if(s.empty()){          // if end left run
                        while(m--){         //   copy rest of right run
                            q.push(q.front());
                            q.pop();
                        }
                        break;              // and break
                    }
                }
            }                               // end merge pair
        }                                   // end merge pass
        r *= 2;                             // double run size
        if(r >= n)                          //  break if sort done
            break;
        // reverse left/even runs in q
        ee = 0;                             // pseudo end index
        while(ee < n){
            size_t ll = ee;                 // ll = pseudo start of left  run
            size_t rr = ll+r;               // rr = pseudo start of right run
            if(rr >= n){                    // if only left run
                while(ll++ < n){            //   copy it and break
                    q.push(q.front());
                    q.pop();
                }
                break;
            }
            ee = rr+r;                      // ee = pseudo end of right run
            if(ee > n)
                ee = n;
            size_t m = rr - ll;             // m = # elements in left run
            while(m--){                     // pop/push left run to s
                s.push(q.front());
                q.pop();
            }
            while(!s.empty()){              // pop/push s to q
                q.push(s.top());            //  (reverse left/even run)
                s.pop();
            }
            m = ee - rr;                    // m = # elements in right run
            while(m--){                     // copy odd run to q
                q.push(q.front());
                q.pop();
            }
        }                                   // end reverse left/even runs
    }                                       // end merge sort
    while(!q.empty()){                      // pop/push q to s
        s.push(q.front());
        q.pop();
    }
}

答案 1 :(得分:0)

这个问题很好。 我亲自检查了你的解决方案,它进入了无限循环,但你的方法非常好。我稍微修改了你使用的逻辑。我尽可能地保留你的方法

我改变的逻辑是首先我将所有堆栈元素复制到队列。然后我使用我的登录来过滤队列并将最高元素逐个插入堆栈。一旦元素(按排序顺序)被推入堆栈,相应的元素就会从队列中删除。

请查看以下我在java上做过的解决方案。我希望它会对你有所帮助..

你必须使用参数i调用(第一次)sort方法。主堆栈,ii。空队列,以及iii。元素的数量(堆栈的大小)..

Employee

答案 2 :(得分:0)

如果您随sortedPosition小于堆栈中元素的数量调用该过程,则您的算法包含一个无限循环,因为:在增加{{1}后,您将无法到达current = S.pop(); }等于currentPosition的次数,那么你将违反sortedPosition条件并且堆栈不为空,那么你肯定会继续增加if m。

currentPosition之后,您应该设置while,而不是currentPosition--;,然后在第一个sortedPosition--;而不是sort中致电sortedPosition调用,它应该等于元素的数量。

正确实施应该是:

currentPosition