数据结构--可排序单链表

可排序单链表

在这里插入图片描述

实现

package pers.zhang.linearList;

/**
 * @author zhang
 * @date 2020/1/14 - 14:22
 *
 * 按升序排序的单链表类,继承单链表类,T必须实现Comparable<T>接口,支持对象可比较大小
 */
public class SortedSinglyLinkedList<T extends Comparable<T>> extends SinglyLinkedList<T> {
    public SortedSinglyLinkedList(){                       //默认构造方法
        super();                                           //调用父类默认构造方法,默认调用,可省略
    }

    //将elements数组中所有对象插入构造排序的单链表,直接插入排序
    public SortedSinglyLinkedList(T[] element){
        super();                                           //创建空单链表,调用父类默认构造方法,默认调用,可省略
        for (int i = 0; i < element.length; i++)           //若element==null,抛出空对象异常
            this.insert(element[i]);                       //插入一个结点,根据值的大小决定插入位置
    }

    //插入值为x结点,根据x值大小插入在合适位置
    //重载父类的insert(i,x)方法,因参数不同没有覆盖父类的insert(i,x)方法
    public void insert(T x){
        if (x == null)
            return;                                         //不能插入空对象
        Node<T> front = this.head, p = front.next;             //front是p的前驱结点
        while (p != null && p.data.compareTo(x) < 0){           //寻找插入位置
            front = p;
            p = p.next;
        }
        front.next = new Node<T>(x, p);                    //创建结点插入在front之后,p之前
    }

    //不支持父类的insert(int i, T x)和append(T x)方法,将其覆盖并抛出异常。
    public void insert(int i, T x){
        throw new UnsupportedOperationException("insert(int i, T x)"); //本类不支持该方法
    }

    public void append(T x){
        throw new UnsupportedOperationException("append(T x)");    //本类不支持该方法
    }

    //删除首次出现的值为x结点,若没找到指定结点则不删除。O(n)
    //重载父类的remove(T x)方法,因参数不同没有覆盖父类的remove(T x)方法
    public void remove(T x){
        if (x == null)
            return;
        Node<T> front = this.head, p = front.next;        //front是p的前驱结点
        while (p != null && p.data.compareTo(x) < 0){      //寻找待删除的结点
            front = p;
            p = p.next;
        }
        if (p != null && p.data.compareTo(x) == 0)
            front.next = p.next;                      //删除p结点
    }

    //深拷贝构造方法,复制单链表
    public SortedSinglyLinkedList(SortedSinglyLinkedList<T> list){
        super(list);                             //调用父类同参数的构造方法,不可省略
    }

    //深拷贝构造方法,由单链表list构造排序单链表,直接插入排序
/*    public SortedSinglyLinkedList(SinglyLinkedList<T> list){
        super();                                 //创建空单链表
        for (Node<T> p = list.head.next;  p != null;  p = p.next)
            this.insert(p.data);                 //根据值的大小决定插入位置,调用排序单链表类的插入方法
    }*/


    //顺序查找关键字为key元素,返回首次出现的元素,若查找不成功返回null
    //key可以只包含关键字数据项,由T类的compareTo()提供比较对象大小和相等的依据
    //覆盖父类SinglyLinkedList的同名方法
    public T search(T key){
        if (key == null)
            return null;
        for (Node<T> p = this.head.next;  p != null && p.data.compareTo(key) <= 0;  p = p.next)
            if (p.data.compareTo(key) == 0)        //由compareTo()提供比较对象大小和相等的依据
                return p.data;
        return null;
    }

    //深拷贝构造方法,由单链表list构造排序单链表,直接选择排序
/*    //第3版程序,每趟寻找最小值结点,交换到前面,通过删除、插入结点方式实现交换
    public SortedSinglyLinkedList(SinglyLinkedList<T> list)
    {
        super(list);                                       //深拷贝list单链表
        Node<T> srear=head;                                //指向排序单链表尾
        while (srear.next!=null)                           //原单链表不空
        {
            Node<T> mfront=srear, min=mfront.next;         //min指向最小值结点,mfront指向min的前驱
            Node<T> pfront=min, p=min.next;                //p遍历单链表,pfront指向p的前驱结点
            while (p!=null)
            {
                if (p.data.compareTo(min.data)<0)          //比较,min记住最小值结点
                {   mfront = pfront;                       //mfront是min的前驱结点
                    min = p;
                }
                pfront = p;                                //pfront是p的前驱结点
                p = p.next;
            }
            if (mfront!=srear)
            {
                mfront.next = min.next;                    //从链表原位置删除min结点
                min.next=srear.next;                       //将min结点插入srear之后
                srear.next = min;
            }
            srear = min;                                   //srear指向排序单链表尾
        }
    }*/

    //深拷贝构造方法,由单链表list构造排序单链表,直接选择排序
    //第4版改进程序,n-1趟,每趟遍历单链表寻找到最小值结点,交换结点元素到前面,不删除和插入结点
    public SortedSinglyLinkedList(SinglyLinkedList<T> list)
    {
        super(list);                                       //深拷贝list单链表
        for (Node<T> first=head.next;  first!=null;  first=first.next) //first指向待排序单链表第一个结点
        {                              //n-1趟,每趟遍历单链表寻找到最小值结点,交换结点元素到前面
            Node<T> min=first;                             //min指向最小值结点
            for (Node<T> p=min.next;  p!=null;  p=p.next)  //遍历单链表一趟,找出最小值结点
                if (p.data.compareTo(min.data)<0)          //比较,min记住最小值结点
                    min = p;
            if (min!=first)                                //交换min结点元素到前面
            {
                T temp = min.data;
                min.data = first.data;
                first.data = temp;
            }
            System.out.println(this.toString());
        }
    }

    //归并两条排序的单链表,将list中所有结点归并到当前排序单链表中,合并后设置list为空
    public void merge(SortedSinglyLinkedList<T> list)
    {
        Node<T> front=this.head, p=front.next;   //p指向this单链表的第一个结点
        Node<T> q=list.head.next;                //q指向list单链表的第一个结点
        while (p!=null && q!=null)
            if ((p.data).compareTo(q.data)<0)    //比较两个单链表当前结点值
            {
                front = p;                       //front指向p的前驱结点
                p = p.next;
            }
            else
            {                                    //将q结点插入到front结点之后
                front.next = q;
                q = q.next;
                front = front.next;
                front.next = p;
            }
        if (q!=null)                             //将list链表中剩余结点并入当前链表尾
            front.next=q;
        list.head.next=null;                     //设置list单链表设置为空链表
    }
}

测试:

package pers.zhang.linearList;

/**
 * @author zhang
 * @date 2020/1/14 - 14:28
 */
public class SortedSinglyLinkedList_ex {
    public static Integer[] random(int n)              //返回产生n个随机数的数组,同例2.3
    {
        Integer[] elements = new Integer[n];
        for (int i=0; i<n; i++)
            elements[i] = (int)(Math.random()*100);   //产生随机数
        return elements;
    }

    public static void main(String args[])
    {
/*
        SortedSinglyLinkedList<Integer> list1 = new SortedSinglyLinkedList<Integer>(random(9));
//        list1.insert(-1, -1);                    //覆盖单链表类的方法,抛出异常
        list1.insert(-2);                        //插入指定值结点,调用排序单链表类的方法
        System.out.println("list1: "+list1.toString());
        SortedSinglyLinkedList<Integer> list2=new SortedSinglyLinkedList<Integer>(list1);//深拷贝
        System.out.println("list2: "+list2.toString());
        list1.remove(list1.length()-1);          //删除最后结点,参数类型是int,调用单链表类的方法
        list1.remove(list1.get(0));              //删除首个结点,参数类型是Integer,调用排序单链表类的方法
        list1.remove(new Integer(50));           //删除指定值结点,可能没删除
        System.out.println("list1: "+list1.toString());
        System.out.println("list2: "+list2.toString());


        SinglyLinkedList<Integer> list3 = new SinglyLinkedList<Integer>(random(9));//单链表
        System.out.println("list3: "+list3.toString());
        SortedSinglyLinkedList<Integer> list4=new SortedSinglyLinkedList<Integer>(list3);//由单链表构造排序单链表
        System.out.println("list4: "+list4.toString());*/


        //由单链表list构造排序单链表,直接选择排序
        SinglyLinkedList<Integer> list1 = new SinglyLinkedList<Integer>(random(7));
        System.out.println("单链表list1: "+list1.toString());
        SortedSinglyLinkedList<Integer> list2 = new SortedSinglyLinkedList<Integer>(list1);
        System.out.println("排序单链表list2: "+list2.toString());
//        list1.set(0, new Integer(list1.get(0).intValue()+100));
//        System.out.println("list1: "+list1.toString());
//        System.out.println("list2: "+list2.toString());
//      list1.merge(list2);                           //归并两条排序单链表
//      System.out.println("归并,list1: "+list1.toString());
//      System.out.println("list2: "+list2.toString());
    }
}

输出如下:

list1: (-2, 1, 21, 21, 23, 44, 59, 65, 83, 95)
list2: (-2, 1, 21, 21, 23, 44, 59, 65, 83, 95)
list1: (1, 21, 21, 23, 44, 59, 65, 83)
list2: (-2, 1, 21, 21, 23, 44, 59, 65, 83, 95)
//习题2
list3: (92, 98, 45, 74, 66, 0, 87, 45, 2)
list4: (0, 2, 45, 45, 66, 74, 87, 92, 98)



归并,list1: (11, 12, 20, 24, 29, 34, 35, 40, 51, 55, 78, 86, 89)
list2: ()

list1: (1, 7, 8, 34, 36)
list2: (27, 78, 85, 90)
归并,list1: (1, 7, 8, 27, 34, 36, 78, 85, 90)
list2: ()

//第9章,由单链表list构造排序单链表,选择排序
list1: (95, 22, 99, 9, 28, 67, 71, 82, 86)
list2: (9, 22, 28, 67, 71, 82, 86, 95, 99)

list1: (70, 45, 53, 48, 11, 1, 4)
list2: (1, 4, 11, 45, 48, 53, 70)
list1: (170, 45, 53, 48, 11, 1, 4)
list2: (1, 4, 11, 45, 48, 53, 70)

//第4版改进程序
单链表list1: (95,79,41,26,45,92,82)
(26,79,41,95,45,92,82)
(26,41,79,95,45,92,82)
(26,41,45,95,79,92,82)
(26,41,45,79,95,92,82)
(26,41,45,79,82,92,95)
(26,41,45,79,82,92,95)
(26,41,45,79,82,92,95)
排序单链表list2: (26,41,45,79,82,92,95)

程序调试情况如下:
        SinglyLinkedList<Object> list3 = new SinglyLinkedList<Object>();
//        SortedSinglyLinkedList<Object> list4 = new SortedSinglyLinkedList<Object>();
                                         //编译错,Object类不能作为E的实际参数,没有实现实现Comparable<E>接口
        SortedSinglyLinkedList<Integer> list4 = new SortedSinglyLinkedList<Integer>();
//        list4.insert(new Object());     //编译错,参数类型不匹配
*/
发布了586 篇原创文章 · 获赞 1815 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/cold___play/article/details/103972667