这是斯坦福大学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。
可选练习:比较基于堆的算法和基于搜索树的算法实现的性能。
我无法找到我的算法有什么问题,所以请发布解决方案!!!