Java - 如何在基于堆的优先级队列中实现函数

时间:2016-10-31 18:34:17

标签: java heap priority-queue

对于编程分配,我一直在创建一个程序来读取输入文件,并使用自制的最大堆优先级队列对数据进行排序。数据文件包含读取"插入[名称] [数字]"或"删除"的行。对于此优先级队列,我们​​需要创建一个插入和删除对象的函数。队列中的每个对象都包含名称作为字符串,优先级作为整数。我必须基于一个大小为255的数组来实现这个堆。

我的问题是,我在执行插入操作时遇到了困难,并且删除了按指定工作的功能。我将提供1)他们需要如何工作,2)我做过的伪代码,以及3)我实现的实际Java代码。我的两个函数都不能完全按照我的意图工作,所以我可以使用更有经验的程序员的指导。

1)insert(name,priority):此函数应采用string类型的名称和integer类型的优先级,并将它们插入优先级队列。    remove():此函数应删除具有最高优先级值的对象,并从对象返回名称字符串。

2)作为背景,我有三个课程:第一,"主要"包含用于读取文件和使用函数的实现的类。第二,"名称" class,用于创建包含名称字符串和优先级int的名称对象,构造函数和compareTo方法,用于比较两个对象的优先级值。第三," priorityqueue" class,包含insert和remove函数。现在,这是我为这两个函数制作的伪代码:

插入:

  • 检查数组是否已满(当num = 255时),如果为true则抛出
  • 使用名称字符串和优先级int
  • 从输入文件创建对象
  • 将对象插入num
  • 使用while循环在插入时交换两个对象
  • 更新num(num ++)

删除:

  • 保存第一个对象
  • 将最后一个对象移动到第一个
  • 更新num(num - )
  • 使用while循环确定较大的子项并将其返回。

3)这是我到目前为止的代码。我会提供我的姓名和优先级队列课程,以防我的名字课给我带来麻烦。

优先级队列类:

public class PriorityQueue 
{
int num; //amount of things in array 
int idx; //index of current name object
Name[] names = new Name[255];

public void insert(String name, int priority)
{
    while (num != 255)
    {
        Name addName = new Name(name, priority);
        names[num] = addName;
        num++;

        while(idx != 0 || names[idx].CompareTo(names[(idx-1)/2]))
        {
            Name temp = names[idx];
            names[idx] = names[(idx-1)/2];
            names[(idx-1)/2] = temp;

            idx = (idx-1)/2;
        }
    }
}

public Name remove()
{
    Name temp2 = names[0];
    //Save first element

    names[0] = names[idx];
    //Move last element to first

    num--;
    while(idx < Math.max(2*idx+1,2*idx+2))
    {
        if(names[idx].CompareTo(names[(idx-1)/2]))
                {
                    Name temp3 = names[idx];
                    names[idx] = names[(idx-1)/2];
                    names[(idx-1)/2] = temp3;
                }
    }
    return temp2;
}

}

名称类:

public class Name implements Comparable
{
String name;
int priority;

public Name(String n, int i)
{
    name = n;
    priority = i;
}

public boolean CompareTo(Name obj)
{
    if(priority < obj.priority)
    {
        return false;
    }

    else if(priority > obj.priority)
    {
        return true;
    }

    return true;
}
}

我感谢任何帮助。谢谢!

1 个答案:

答案 0 :(得分:0)

几个问题。首先,在您的#Ecto.Changeset<action: :insert, changes: %{cnpj: "01578216908926", roles: [#Ecto.Changeset<action: :insert, changes: %{}, errors: [name: {"is invalid", [type: :string]}], data: #Module.Role<>, valid?: false>], name: "xxx"}, errors: [], data: #Module.User<>, valid?: false> 方法中:

insert

public void insert(String name, int priority) { while (num != 255) { Name addName = new Name(name, priority); names[num] = addName; num++; while(idx != 0 || names[idx].CompareTo(names[(idx-1)/2])) { Name temp = names[idx]; names[idx] = names[(idx-1)/2]; names[(idx-1)/2] = temp; idx = (idx-1)/2; } } } 不应该在那里。您应该检查是否while (num != 255),如果是,则抛出异常。

然后,您需要初始化num == 255。那就是:

idx

您的 Name addName = new Name(name, priority); names[num] = addName; idx = num; num++; 条件应使用while而不是&&。否则,每当||不等于0时,您就会进行交换。

idx方法中:

remove

你不希望public Name remove() { Name temp2 = names[0]; //Save first element names[0] = names[idx]; //Move last element to first num--; while(idx < Math.max(2*idx+1,2*idx+2)) { if(names[idx].CompareTo(names[(idx-1)/2]) > 0) { Name temp3 = names[idx]; names[idx] = names[(idx-1)/2]; names[(idx-1)/2] = temp3; } } return temp2; } 出现在那里,因为你不知道names[idx]是什么。你想要:

idx

这里的names[0] = names[num-1]; // get last item in the heap 条件很愚蠢。 while将始终返回Math.max(2*idx+1,2*idx+2),除非2*idx+2为否定。而且,你甚至没有初始化idx。你想要的是:

idx

现在,您要做的是查看idx = 0; while (idx < num) 是否小于其中一个孩子。如果是这样,请选择两个孩子中最大的孩子进行交换。所以:

names[idx]

我建议在两种方法中使while (idx < num) { int largestChild = idx*2+1; if (largestChild >= num) break; // idx is at a leaf level if (largestChild+1 < num) { // compare the two children if (names[largestChild].compareTo(names[largestChild+1]) < 0) { largestChild = largestChild+1; } } if (names[idx] < names[largestChild]) { // swap, moving the item down temp = names[idx]; names[idx] = names[largestChild]; names[largestChild] = temp; idx = largestChild; } else { // item is in the proper place break; } } 成为方法范围的变量。它不需要它是全局的,并且使它在方法本地强制您在使用它之前初始化它,而不是潜在地(如在现有代码中)使用陈旧值。

我认为您需要更改idx班级Name功能。 $project CompareTo函数必须返回:

  

负整数,零或正整数,因为此对象小于,等于或大于指定对象。

所以你应该:

compareTo