在Java中递归合并排序LinkedList

在Java中递归合并排序LinkedList,java,linked-list,mergesort,singly-linked-list,Java,Linked List,Mergesort,Singly Linked List,因此,任务是实现一个链表和合并排序,对链表进行排序。我完全知道,在工业界,我很可能不需要实现这些,但我觉得这是练习Java的好方法。以下是我到目前为止的情况: 节点类: public class Node<E extends Comparable<E>> { public E data; public Node<E> next; public Node(E data) { this.data = da

因此,任务是实现一个链表和合并排序,对链表进行排序。我完全知道,在工业界,我很可能不需要实现这些,但我觉得这是练习Java的好方法。以下是我到目前为止的情况:

节点类:

public class Node<E extends Comparable<E>>
    {

    public E data;
    public Node<E> next;

    public Node(E data)
    {
        this.data = data;
        next = null;
    }

    public void printData()
    {
        System.out.print(data + " ");
    }
}
public class LinkedList<E extends Comparable<E>>
{

    protected Node<E> root;
    protected int size = 0;

    public LinkedList()
    {
        root = null;
    }


    public void addBeg(E e)
    {

        Node<E> newNode = new Node<E>(e);
        newNode.next = root;
        root = newNode;

        size++;
    }

    public Node deleteBeg()
    {
        Node<E> temp = root;
        if(!isEmpty())
        {
            root = root.next; 
            size--;
        }
        return temp;
    }

    public void setRoot(Node<E> newRoot)
    {
        root = newRoot;
    }

    public boolean isEmpty()
    {
        return root == null;
    }

    public Node<E> getRoot()
    {
        return root;
    }

    public void printList()
    {
        Node<E> cur = root;   
        while(cur!=null)
            {
                cur.printData();
                cur=cur.next;
            }
        System.out.println();        
    }
}
public class MergeSorter<E extends Comparable<E>>
{

    public MergeSorter()
    {

    }

    private void split(LinkedList<E> list, LinkedList<E> firHalf, LinkedList<E> secHalf)
    {
        //if 0 or only 1 elements in the list - it doesn't seem to work, however
        if(list.getRoot() == null || list.getRoot().next == null)firHalf = list;
        else{
            Node<E> slow = list.getRoot(); 
            Node<E> fast = list.getRoot().next; 
            while(fast!=null)
            {
                fast = fast.next;
                if(fast!=null)
                {
                    fast = fast.next;
                    slow = slow.next;
                } 
            }
            //If I use the following line firHalf list is empty when in the caller of this method (it's not in this method, however). Don't understand why ):
            //firHalf = list; 
            firHalf.setRoot(list.getRoot());
            secHalf.setRoot(slow.next);
            slow.next = null;
        }

    }



    private LinkedList<E> merge(LinkedList<E> a, LinkedList<E> b)
     {
        LinkedList<E> mergedList = new LinkedList<E>();    
        Node<E> dummy = new Node<E>(null);
        Node<E> tail = dummy;

        while(true)
        {         
            if(a.getRoot() == null){
                tail.next = b.getRoot();
                break;
            }
            else if(b.getRoot() == null){
                tail.next = a.getRoot();
                break;
            }

            else 
            {
                if(a.getRoot().data.compareTo(b.getRoot().data) <= 0)
                {
                    tail.next = a.getRoot();
                    tail = tail.next;
                    a.setRoot(a.getRoot().next);
                }

                else
                {   
                    tail.next = b.getRoot();
                    tail = tail.next;
                    b.setRoot(b.getRoot().next);
                }
                tail.next = null;
            }

        }
        mergedList.setRoot(dummy.next);
        return mergedList;
    }

    public void mergeSort(LinkedList<E> list)
    {
        Node<E> root = list.getRoot();
        LinkedList<E> left  = new LinkedList<E>();
        LinkedList<E> right = new LinkedList<E>();

        if(root == null || root.next == null) return; //base case
        split(list, left, right); //split

        mergeSort(left);
        mergeSort(right);

        list = merge(left, right); // when this mergeSort returns this list should be  
                                   // referenced by the left or right variable of the 
                                   // current mergeSort call (but it isn't!)
    }
}
公共类节点
{
公共电子数据;
公共节点下一步;
公共节点(E数据)
{
这个数据=数据;
next=null;
}
public void printData()
{
系统输出打印(数据+“”);
}
}
LinkedList类:

public class Node<E extends Comparable<E>>
    {

    public E data;
    public Node<E> next;

    public Node(E data)
    {
        this.data = data;
        next = null;
    }

    public void printData()
    {
        System.out.print(data + " ");
    }
}
public class LinkedList<E extends Comparable<E>>
{

    protected Node<E> root;
    protected int size = 0;

    public LinkedList()
    {
        root = null;
    }


    public void addBeg(E e)
    {

        Node<E> newNode = new Node<E>(e);
        newNode.next = root;
        root = newNode;

        size++;
    }

    public Node deleteBeg()
    {
        Node<E> temp = root;
        if(!isEmpty())
        {
            root = root.next; 
            size--;
        }
        return temp;
    }

    public void setRoot(Node<E> newRoot)
    {
        root = newRoot;
    }

    public boolean isEmpty()
    {
        return root == null;
    }

    public Node<E> getRoot()
    {
        return root;
    }

    public void printList()
    {
        Node<E> cur = root;   
        while(cur!=null)
            {
                cur.printData();
                cur=cur.next;
            }
        System.out.println();        
    }
}
public class MergeSorter<E extends Comparable<E>>
{

    public MergeSorter()
    {

    }

    private void split(LinkedList<E> list, LinkedList<E> firHalf, LinkedList<E> secHalf)
    {
        //if 0 or only 1 elements in the list - it doesn't seem to work, however
        if(list.getRoot() == null || list.getRoot().next == null)firHalf = list;
        else{
            Node<E> slow = list.getRoot(); 
            Node<E> fast = list.getRoot().next; 
            while(fast!=null)
            {
                fast = fast.next;
                if(fast!=null)
                {
                    fast = fast.next;
                    slow = slow.next;
                } 
            }
            //If I use the following line firHalf list is empty when in the caller of this method (it's not in this method, however). Don't understand why ):
            //firHalf = list; 
            firHalf.setRoot(list.getRoot());
            secHalf.setRoot(slow.next);
            slow.next = null;
        }

    }



    private LinkedList<E> merge(LinkedList<E> a, LinkedList<E> b)
     {
        LinkedList<E> mergedList = new LinkedList<E>();    
        Node<E> dummy = new Node<E>(null);
        Node<E> tail = dummy;

        while(true)
        {         
            if(a.getRoot() == null){
                tail.next = b.getRoot();
                break;
            }
            else if(b.getRoot() == null){
                tail.next = a.getRoot();
                break;
            }

            else 
            {
                if(a.getRoot().data.compareTo(b.getRoot().data) <= 0)
                {
                    tail.next = a.getRoot();
                    tail = tail.next;
                    a.setRoot(a.getRoot().next);
                }

                else
                {   
                    tail.next = b.getRoot();
                    tail = tail.next;
                    b.setRoot(b.getRoot().next);
                }
                tail.next = null;
            }

        }
        mergedList.setRoot(dummy.next);
        return mergedList;
    }

    public void mergeSort(LinkedList<E> list)
    {
        Node<E> root = list.getRoot();
        LinkedList<E> left  = new LinkedList<E>();
        LinkedList<E> right = new LinkedList<E>();

        if(root == null || root.next == null) return; //base case
        split(list, left, right); //split

        mergeSort(left);
        mergeSort(right);

        list = merge(left, right); // when this mergeSort returns this list should be  
                                   // referenced by the left or right variable of the 
                                   // current mergeSort call (but it isn't!)
    }
}
公共类链接列表
{
受保护的节点根;
受保护的整数大小=0;
公共链接列表()
{
root=null;
}
公共无效地址(E)
{
Node newNode=新节点(e);
newNode.next=root;
根=新节点;
大小++;
}
公共节点deleteBeg()
{
节点温度=根;
如果(!isEmpty())
{
root=root.next;
大小--;
}
返回温度;
}
公共void setRoot(节点newRoot)
{
根=新根;
}
公共布尔值为空()
{
返回root==null;
}
公共节点getRoot()
{
返回根;
}
公共作废打印列表()
{
节点cur=根;
while(cur!=null)
{
cur.printData();
cur=cur.next;
}
System.out.println();
}
}
合并分拣机类别:

public class Node<E extends Comparable<E>>
    {

    public E data;
    public Node<E> next;

    public Node(E data)
    {
        this.data = data;
        next = null;
    }

    public void printData()
    {
        System.out.print(data + " ");
    }
}
public class LinkedList<E extends Comparable<E>>
{

    protected Node<E> root;
    protected int size = 0;

    public LinkedList()
    {
        root = null;
    }


    public void addBeg(E e)
    {

        Node<E> newNode = new Node<E>(e);
        newNode.next = root;
        root = newNode;

        size++;
    }

    public Node deleteBeg()
    {
        Node<E> temp = root;
        if(!isEmpty())
        {
            root = root.next; 
            size--;
        }
        return temp;
    }

    public void setRoot(Node<E> newRoot)
    {
        root = newRoot;
    }

    public boolean isEmpty()
    {
        return root == null;
    }

    public Node<E> getRoot()
    {
        return root;
    }

    public void printList()
    {
        Node<E> cur = root;   
        while(cur!=null)
            {
                cur.printData();
                cur=cur.next;
            }
        System.out.println();        
    }
}
public class MergeSorter<E extends Comparable<E>>
{

    public MergeSorter()
    {

    }

    private void split(LinkedList<E> list, LinkedList<E> firHalf, LinkedList<E> secHalf)
    {
        //if 0 or only 1 elements in the list - it doesn't seem to work, however
        if(list.getRoot() == null || list.getRoot().next == null)firHalf = list;
        else{
            Node<E> slow = list.getRoot(); 
            Node<E> fast = list.getRoot().next; 
            while(fast!=null)
            {
                fast = fast.next;
                if(fast!=null)
                {
                    fast = fast.next;
                    slow = slow.next;
                } 
            }
            //If I use the following line firHalf list is empty when in the caller of this method (it's not in this method, however). Don't understand why ):
            //firHalf = list; 
            firHalf.setRoot(list.getRoot());
            secHalf.setRoot(slow.next);
            slow.next = null;
        }

    }



    private LinkedList<E> merge(LinkedList<E> a, LinkedList<E> b)
     {
        LinkedList<E> mergedList = new LinkedList<E>();    
        Node<E> dummy = new Node<E>(null);
        Node<E> tail = dummy;

        while(true)
        {         
            if(a.getRoot() == null){
                tail.next = b.getRoot();
                break;
            }
            else if(b.getRoot() == null){
                tail.next = a.getRoot();
                break;
            }

            else 
            {
                if(a.getRoot().data.compareTo(b.getRoot().data) <= 0)
                {
                    tail.next = a.getRoot();
                    tail = tail.next;
                    a.setRoot(a.getRoot().next);
                }

                else
                {   
                    tail.next = b.getRoot();
                    tail = tail.next;
                    b.setRoot(b.getRoot().next);
                }
                tail.next = null;
            }

        }
        mergedList.setRoot(dummy.next);
        return mergedList;
    }

    public void mergeSort(LinkedList<E> list)
    {
        Node<E> root = list.getRoot();
        LinkedList<E> left  = new LinkedList<E>();
        LinkedList<E> right = new LinkedList<E>();

        if(root == null || root.next == null) return; //base case
        split(list, left, right); //split

        mergeSort(left);
        mergeSort(right);

        list = merge(left, right); // when this mergeSort returns this list should be  
                                   // referenced by the left or right variable of the 
                                   // current mergeSort call (but it isn't!)
    }
}
公共类合并分类器
{
公共分拣机()
{
}
私有无效拆分(LinkedList、LinkedList firHalf、LinkedList secHalf)
{
//如果列表中只有0个或1个元素,那么它似乎不起作用
如果(list.getRoot()==null | | list.getRoot().next==null)firHalf=list;
否则{
Node slow=list.getRoot();
Node fast=list.getRoot().next;
while(快速!=null)
{
fast=fast.next;
如果(快速!=null)
{
fast=fast.next;
slow=slow.next;
} 
}
//如果我使用以下行,则当在该方法的调用方中时,firHalf列表为空(但不在此方法中)。不理解原因:
//firHalf=列表;
firHalf.setRoot(list.getRoot());
setRoot(slow.next);
slow.next=null;
}
}
私有链接列表合并(链接列表a、链接列表b)
{
LinkedList mergedList=新建LinkedList();
节点虚拟=新节点(空);
节点尾部=虚拟;
while(true)
{         
如果(a.getRoot()==null){
tail.next=b.getRoot();
打破
}
else if(b.getRoot()==null){
tail.next=a.getRoot();
打破
}
其他的
{

Java中的if(a.getRoot().data.compareTo(b.getRoot().data)方法参数总是按值传递

这可能有点令人困惑,因为对象总是通过引用访问的,所以您可能认为它们是通过引用传递的;但事实并非如此。相反,引用是通过值传递的

这意味着,像这样的方法:

public void methodThatDoesNothing(Object dst, Object src) {
    src = dst;
}
实际上什么也不做。它修改其局部变量
src
以引用与局部变量
dst
相同的对象,但这些只是局部变量,在函数返回时消失。它们与传递到方法中的任何变量或表达式完全分离

因此,在您的代码中:

firHalf = list;
我想你想要的是:

while (! firHalf.isEmpty()) {
    firHalf.deleteBeg();
}
if (! list.isEmpty()) {
    firHalf.addBeg(list.root().data);
}

它修改了由
firHalf
引用的objected,因此它具有与
list
相同的零或一个元素。啊,我明白你的意思。非常感谢!但是,在我看来,对于这样一个简单的任务来说,代码太多了。这不是:firHalf.setRoot(list.getRoot());做同样的工作?我想传递值也是递归返回时我的mergeSort方法中的合并不能正常工作的原因(:因此,在我的mergeSort方法中,我添加了一个新的LinkedList mergedList来存储左侧和右侧的合并列表:mergedList=merge(left,right),然后我通过list.setRoot(mergedList.getRoot())将list的根目录设置为与此mergedList的根目录相同,并且它成功了!但是,我觉得我的解决方案过于复杂(例如,与用C编写的解决方案相比)。我的代码中有什么可以改进的地方吗?再次感谢!(:@user3192253:
firHalf.setRoot(list.getRoot())
firHalf
list
设置为具有相同的实际根节点,而不仅仅是相同的根值。这意味着如果有人要编写
list.getRoot().value=…
list.getRoot()).next=…
,这将改变两个列表。因此…是的,您应该这样做,但只有在您将
节点
类更改为不可变之后,才能在多个列表之间安全地共享它。(也就是说:
Node.value
Node.next
都应该声明为
final
,并在构造函数中初始化。)(或者,您可以给您的
Node
类一个递归复制列表的方法,然后编写
firHalf.setRoot(list.getRoot().clone())
。但我认为不可变路径更好。)好的,多谢各位。再说一次。但是,如果我将
节点
更改为不可变,那么某些算法(如反转链表或附加两个列表)将更难实现(因为两者都需要更改
节点。下一步
)。如果这是最终声明,则我需要创建新节点的完整新链接列表,而不是仅更改当前节点的节点引用):