我的维护算法中位数不起作用...(Java)

时间:2016-12-11 11:08:19

标签: java heap

这是斯坦福大学Coursera课程图形搜索,最短路径和数据结构的任务。任务是为此特定流实现中值维护算法https://d3c33hcgiwev3.cloudfront.net/_6ec67df2804ff4b58ab21c12edcb21f8_Median.txt?Expires=1481500800&Signature=MY3YWOJaldKZE1Ea8gxGNUe9SybX1q~OZD2htX9hPHxAJ-OB6b-iCWCtpacqBY9g7j9AUoIEzZm56f7iZ6fZWdrrCH4d6c6hMiaCBDlBaliRT7W6AP2XQoqhKcqiKW8OzeKVgDQSf0O0ASqKHkdP0FAjVGfSYirysQPZl6Y8iF8_&Key-Pair-Id=APKAJLTNE6QMUY6HBC5A

我在Java中的代码基于两个堆:min_heap-当我们从底部到顶部时元素较小的堆和max_heap-当我们从哪里开始元素更大的堆对于前两个流元素,我将较小的一个放在max_heap中,将较大的一个放在min_heap中。然后为每个新元素,我检查它是否小于max_heap的根 - 如果是,我把它插入到max_heap中。如果不是,我将它插入min_heap。然后我检查两个堆的余额 - 它们的大小在多个元素中不能有所不同。如果一个堆的大小超过一个比另一个堆的大小,我删除更大堆的根,然后我将其插入较小的堆中。然后我检查中位数。中位数应该是两个堆根的平均值,如果它们的大小相等,或者一个更大的堆的根。我按照中位数递增一个变量计数,并在结束流循环后,打印计数模10000.It打印出来9651,它应该打印出1213(为了记录,我确实以合适的方式增加了流的前两个元素的计数)。

对于我的算法,我使用两个Java类。第一个是Heap类:

import java.util.ArrayList;
import java.util.NoSuchElementException;
public class Heap<T extends Comparable<T>> {

    private ArrayList<T> items;
    boolean maximum;

    public Heap( boolean max){
        items = new ArrayList<T>();
        maximum = max;
    }

    private void siftUp()
    {
        if(maximum)
        {
            int k = items.size()-1;
            while(k>0)
            {
                int p = (int)(Math.floor((k-1)/2));
                T item = items.get(k);
                T parent = items.get(p);
                if(item.compareTo(parent)>0)
                {
                    T temp = items.get(k);
                    items.set(k, parent);
                    items.set(p, temp);
                    k=p;
                }
                else{
                    break;
                }
            }
        }
        else
        {
            int k = items.size()-1;
            while(k>0)
            {
                int p = (int)(Math.floor((k-1)/2));
                T item = items.get(k);
                T parent = items.get(p);
                if(item.compareTo(parent)<0)
                {
                    T temp = items.get(k);
                    items.set(k, parent);
                    items.set(p,temp);
                    k=p;
                }
                else
                {
                    break;
                }

            }
        }
    }

    public void insert(T item)
    {
        items.add(item);
        siftUp();
    }

    private void siftDown()
    {
        if(maximum)
        {
            int k =0;
            int l=2*k+1;
            while(l<items.size())
            {
                int max=l,r=l+1;
                if(r<items.size())
                {
                    if(items.get(r).compareTo(items.get(l))>0)
                    {
                        max++;
                    }
                }
                if(items.get(k).compareTo(items.get(max))<0)
                {
                    T temp = items.get(k);
                    items.set(k, items.get(max));
                    items.set(max,temp);
                    k=max;
                    l=2*k+1;
                }
                else
                {
                    break;
                }
            }
        }
        else
        {
            int k =0;
            int l =2*k+1;
            while(l<items.size())
            {
                int min = l,r=l+1;
                if(r<items.size())
                {
                    if(items.get(r).compareTo(items.get(l))<0)
                    {
                        min++;
                    }
                }
                if(items.get(k).compareTo(items.get(min))>0)
                {
                    T temp = items.get(k);
                    items.set(k,items.get(min));
                    items.set(min,temp);
                    k = min;
                    l= 2*k+1;
                }
                else
                {
                    break;
                }
            }
        }

    }

    public T delete()
            throws NoSuchElementException{
        if(items.size()==0)
        {
            throw new NoSuchElementException();
        }
        if(items.size()==1)
        {
            return items.remove(0);
        }
        T hold = items.get(0);
        items.set(0,items.remove(items.size()-1));
        siftDown();
        return hold;
    }

    public int size()
    {
        return items.size();
    }

    public boolean isEmpty()
    {
        return items.isEmpty();
    }

    public String toString()
    {
        return items.toString();
    }

    public T peek()
    throws NoSuchElementException{
        if(items.size()==0)
        {
            throw new NoSuchElementException();
        }
        return items.get(0);
    }


}

这是Medheap课程:

import java.io.IOException;
import java.net.URL;
import java.util.*;

public class Medheap {


    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Heap<Integer> max_heap = new Heap<Integer>(true);
        Heap<Integer> min_heap = new Heap<Integer>(false);
        int count = 0;
        int temp = 0;


try{

    URL url = new        URL("https://d3c33hcgiwev3.cloudfront.net/_6ec67df2804ff4b58ab21c12edcb21f8_Median.txt?Expires=1481500800&Signature=MY3YWOJaldKZE1Ea8gxGNUe9SybX1q~OZD2htX9hPHxAJ-OB6b-iCWCtpacqBY9g7j9AUoIEzZm56f7iZ6fZWdrrCH4d6c6hMiaCBDlBaliRT7W6AP2XQoqhKcqiKW8OzeKVgDQSf0O0ASqKHkdP0FAjVGfSYirysQPZl6Y8iF8_&Key-Pair-Id=APKAJLTNE6QMUY6HBC5A");
    Scanner in = new Scanner(url.openStream());
    for(int i = 0;i<10000;i++)
    {
        int line = Integer.parseInt(in.nextLine());
        if(i==0)
        {
            count+=line;
            temp=line;
        }
        else if(i==1)
        {
            if(line<temp)
            {
                max_heap.insert(line);
                min_heap.insert(temp);
                count+=line;
            }
            else
            {
                max_heap.insert(temp);
                min_heap.insert(line);
                count+=temp;
            }
        }
        else
        {
            if(line<max_heap.peek())
            {
                max_heap.insert(line);
            }
            else
            {
                min_heap.insert(line);
            }
            if(min_heap.size()+1<max_heap.size())
            {
                min_heap.insert(max_heap.delete());
            }
            if(max_heap.size()+1<min_heap.size())
            {
                max_heap.insert(min_heap.delete());
            }

            int median = 0;
            if(max_heap.size()==min_heap.size())
            {
                median =(int)            (Math.floor((max_heap.peek()+min_heap.peek())/2));

            }
            else
            {
                if(max_heap.size()>min_heap.size())
                {
                    median = max_heap.peek();
                }
                else
                {
                    median = min_heap.peek();
                }
            }
            count+=median;

        }
    }
    in.close();


}
catch(IOException ex)
{
    ex.printStackTrace();
}
System.out.println(count%10000);
    }

}

这是编程任务的文本:

下载以下文本文件:

Median.txt

此问题的目标是实现“中位维护”算法(在第3周关于堆应用程序的讲座中介绍)。文本文件包含未排序顺序的1到10000之间的整数列表;你应该把它视为一个数字流,一个接一个地到达。令xi表示文件的第i个数,第k个中值mk被定义为数字x1,...,xk的中值。 (因此,如果k是奇数,则mk是((k + 1)/ 2)x1,...,xk中的最小数;如果k是偶数,则mk是x1中的第(k / 2)个最小数, ...,XK。)

在下面的框中,您应键入这些10000个中位数的总和,模数为10000(即仅最后4个数字)。也就是说,你应该计算(m1 + m2 + m3 +⋯+ m10000)mod10000。

可选练习:比较基于堆的算法和基于搜索树的算法实现的性能。

我无法找到我的算法有什么问题,所以请发布解决方案!!!

0 个答案:

没有答案