【问题标题】:Linked list merge sort using java使用java的链表合并排序
【发布时间】:2016-11-30 10:20:53
【问题描述】:

我想用没有任何数组的链表实现归并排序,使用java。但我陷入了一个逻辑错误;我的代码消除了一些输入并对剩余部分进行排序。我申请了三个类:DivideMergMergSort,如下:

public class Divide {

    List firstList = new List();
    List secondList = new List();

    public int GetLength(List list) {
        int Length = 0;
        Link temp = new Link();
        temp.next = list.head.next;
        while (temp.next != null) {
            temp.next = temp.next.next;
            Length++;
        }

        return Length;
    }

    public List rightSide(List list) {
        int Length = GetLength(list);
        Link temp = new Link();
        temp.next = list.head.next;

            for (int i = 1; i <= Math.floor(Length / 2); i++) {
                firstList.Insert(temp.next.data);
                temp.next = temp.next.next;
            }
            return firstList;
    }

    public List leftSide(List list) {
        int Length = GetLength(list);
        Link temp = new Link();
        temp.prev = list.head.prev;

            for (int i = 1; i <= Math.ceil(Length / 2); i++) {
                secondList.Insert( temp.prev.data);
                temp.prev =  temp.prev.prev;
            }
            return secondList;
        }
    }

合并:

public class Merg {

    public List MergedList = new List();
    private  List Temp = new List();

    public List Merg (List one, List two)
    {
        Link onelink = new Link();
        Link twolink = new Link();

        onelink.next = one.head.next;
        twolink.next = two.head.next;

        while (onelink.next!= null || twolink.next!= null)
        {

            if(onelink.next!= null && twolink.next != null)
            {
              if(onelink.next.data < twolink.next.data)
              {
                  Temp.Insert(onelink.next.data);
                  onelink.next = onelink.next.next;
              }
              else
              {
                  Temp.Insert(twolink.next.data);
                  twolink.next = twolink.next.next;
              }

            }

            if (onelink.next != null && twolink.next == null)
            {
                Temp.Insert(onelink.next.data);
                onelink.next = onelink.next.next;
            }
            if (twolink.next != null && onelink.next == null)
            {
                Temp.Insert(twolink.next.data);
                twolink.next = twolink.next.next;
            }

        }

        if (Temp.head.next.data > Temp.head.prev.data)
        {
            while (Temp.head.next != null)
            {
                MergedList.Insert(Temp.head.next.data);
                Temp.head.next = Temp.head.next.next;
            }
        }

        else
        {
            MergedList.head.next = Temp.head.next;
        }


        return MergedList;
    }

}

合并排序:

public class MergSort {

    public List mergSort (List list)
    {
        Divide divide = new Divide();
        Merg merg = new Merg();

        if (divide.GetLength(list) > 1) {
            return merg.Merg(mergSort(divide.leftSide(list)), mergSort(divide.rightSide(list)));
        }
        else
        {
            return list;
        }
    }
}

虽然我也写了linklist 类,但我认为那里没有问题。 (但是如果有必要我会提到它们) 现在,当我导入一些输入时:{100,3,1,7,6} 输出为:3,6,7,100。 (1 已被淘汰!)或另一个例子:{100,3,1} 输出为:1,100(3 在哪里??)

我想知道是否有人可以帮助我...

链接:

public class Link {
    public double data;
    public Link prev;
    public Link next;
}

列表:

public class List {
    public Link head = new Link();

    public void setHead(Link head) {
        this.head = head;
        head.prev = null;
        head.next = null;
    }

    public void Insert(double x)
    {
        Link link = new Link();
        link.data = x;
        if (head.next == null)
        {
            head.next = link;
            head.prev = link;
        }
        else
        {
            head.next.prev = link;
            link.next = head.next;
            head.next = link;
        }
    }

    public Link delete()
    {
        Link temp = new Link();
        temp = head;
        head = head.next;
        return temp;
    }

    public Link search(double x)
    {
        Link link = new Link();
        link.next = head;
        while (link.next.data != x)
        {
            link.next = link.next.prev;
        }

        return link.next;
    }
}

【问题讨论】:

  • 请调试您的代码。它会一步一步地告诉你正在发生的事情。
  • 你试过用调试器调试它吗?为什么dividemerge 有不同的类?是不是有点太复杂了?
  • 链接和列表类在哪里?
  • 你的Merg 类只检查onelink.next.data &lt; twolink.next.data(反之亦然)——如果它们相等怎么办?
  • @Prasath 我已经写了它们,但你真的认为问题出在那儿吗?我的意思是其他班级没有疑似病例?如果是这样,我编辑我的帖子并添加它们......

标签: java sorting linked-list mergesort


【解决方案1】:

我已经调试了很多,但我无法理解您的 Divide 类。你根本不需要它。

public class MergSort {

    public List mergSort(List list) {
        Divide divide = new Divide();
        Merg merg = new Merg();
        int n = list.getLength();
        if (n > 1) {
//            return merg.Merg(mergSort(divide.leftSide(list)), mergSort(divide.rightSide(list)));
            Link cursor = list.head.next;
            List left = new List();
            List right = new List();
            // for (i = 0; ....... i will be 0 if head is not dummy
            for (int i = 1; cursor != null; i++) {
                if (i <= n/2)
                    left.Insert(cursor.data);
                else
                    right.Insert(cursor.data);
                cursor = cursor.next;
            }
            left = mergSort(left);
            right = mergSort(right);

            return merg.Merg(left, right);

        } else {
            return list;
        }
    }
}

在您的 List 类中创建一个 getLength() 方法。它应该在 List 类中,因为您想要列表的长度。

public int getLength() {
    int Length = 0;
    Link temp = head.next;
    while (temp != null) {
        temp = temp.next;
        Length++;
    }

    return Length;
}

另外,将Link 类重命名为Node。因为Link 表示对象之间的链接 或节点之间的边。你真正想要的是Node。很混乱。

在您的 List 类中,您已像这样定义 head

public Link head = new Link();

我不明白你为什么需要dummy headed linked list

具有虚拟头的链表基本上是一个没有值的头,因此是虚拟的。

由于您的虚拟头,您正在从i = 1 开始在Divide 类中的for 循环。为什么要把事情复杂化?如果你真的需要一个假头,那么保留它或像这样定义它:

public Link head;
// don't instantiate the head. It's just a reference

另外,您似乎创建了一个半圆形链表。我的意思是head.prev 指向列表中的最后一个链接/节点。如果您真的想要一个循环链表,请将您的 tail.next 指向头部。

这是一个循环链表的样子:

或者,如果您不想要一个循环列表,那么不要将您的 head.prev 指向最后一个对象。

List.java 中的Insert() 方法中:

if (head.next == null)
{
    head.next = link;
    // remove head.prev = link;
}

【讨论】:

  • 如果是带有虚拟(又名哨兵或头)节点的双链表,则 dummy.prev 指向列表中的最后一个节点,如您所述,dummy.prev.next (last node.next) 指向虚拟对象。
  • @rcgldr 按照惯例,具有虚拟头的双链表的 head.prev 设置为 null。
  • @rcgldr 是的,我同意你的观点,但这里的 OP 并没有完全循环。在 OP 的实现中,lastNode.next == null。另外,在我之前的评论中,我说的是双(但不是循环)链表。
  • 感谢您的回复!你的提示对我很有用。
  • @RafiduzzamanSonnet - 即使在空终止列表的情况下,使用 head.prev 指向最后一个节点也允许快速追加,使用虚拟节点作为头和尾指针的容器。排序完成后需要更新 head.prev。我同意空终止的链表不需要虚拟节点。为循环列表设置一个虚拟节点会更有意义,但即使这样也不需要。对于循环列表,只需要一个尾引用,因为 head 可以随时使用 head = tail.next 创建。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 2013-06-04
  • 1970-01-01
  • 2017-04-03
相关资源
最近更新 更多