java 单链表实现 及 反转单链表

单链表的概念很容易理解,就是单向链表的意思。

下面直接给出实现:

import java.util.Arrays;
import java.util.Random;
import java.util.StringJoiner;

/**
 * 单链表的实现.
 */
public class LinkedList<Z> {

    private static class Node<K> {
        K data;
        Node<K> next;
    }

    private final Node<Z> head = new Node<>();

    private int length = 0;

    public LinkedList() {
        head.data = null;
        head.next = null;
    }

    public int size() {
        return length;
    }

    public boolean isEmpty() {
        return length == 0;
    }

    public boolean add(Z data) {
        return insert(0, data);
    }

    public boolean addLast(Z data) {
        return insert(length, data);
    }

    public boolean set(int index, Z data) {
        int pos = -1;
        Node<Z> h = head;
        while (h.next != null) {
            if (index - 1 == pos) {
                break;
            }
            h = h.next;
            pos++;
        }
        if (pos == length) {
            return false;
        }
        Node<Z> old = h.next;
        Node<Z> young = new Node<>();
        young.data = data;
        h.next = young;
        //noinspection ConstantConditions
        young.next = old.next;
        old.data = null;
        return true;
    }

    public boolean replace(int index, Z data) {
        int pos = -1;
        Node<Z> h = head;
        while (h.next != null) {
            if (index == pos) {
                break;
            }
            h = h.next;
            pos++;
        }
        if (pos == length) {
            return false;
        }
        h.data = data;
        return true;
    }

    // a [k] b c d
    public boolean insert(int index, Z data) {
        if (index < 0 || index > length) {
            return false;
        }
        int pos = -1;
        Node<Z> h = head;
        while (h.next != null) {
            if (index - 1 == pos) {
                break;
            }
            h = h.next;
            pos++;
        }
        if (pos == length) {
            return false;
        }
        Node<Z> old = h.next;
        Node<Z> young = new Node<>();
        young.data = data;
        h.next = young;
        young.next = old;
        length++;
        return true;
    }

    public int indexOf(Z data) {
        int pos = -1;
        if (data == null) {
            return pos;
        }
        Node<Z> h = head;
        while (h.next != null) {
            if (data.equals(h.data)) {
                break;
            }
            h = h.next;
            pos++;
        }
        return pos;
    }

    public Z get(int index) {
        if (index < 0 || index >= length) {
            return null;
        }
        int pos = -1;
        Node<Z> h = head;
        while (h.next != null) {
            if (index == pos) {
                break;
            }
            h = h.next;
            pos++;
        }
        if (pos == length) {
            return null;
        }
        return h.data;
    }

    public boolean remove(Z data) {
        return remove(indexOf(data));
    }

    public boolean removeLast() {
        return remove(length - 1);
    }

    public boolean removeFirst() {
        return remove(0);
    }

    public boolean remove(int index) {
        if (index < 0 || index >= length) {
            return false;
        }
        int pos = -1;
        Node<Z> h = head;
        while (h.next != null) {
            if (index - 1 == pos) {
                break;
            }
            h = h.next;
            pos++;
        }
        if (pos == length) {
            return false;
        }
        // now h' pos == index-1
        Node<Z> target = h.next;
        //noinspection ConstantConditions
        h.next.data = null; // remove target
        h.next = target.next;
        length -= 1;
        return true;
    }

    public boolean clear() {
        while (length > 0) {
            removeFirst();
        }
        return true;
    }

    public void reverse() {
        if (isEmpty()) {
            return;
        }
        Object[] zs = new Object[size()];
        Node<Z> h = head;
        int pos = -1;
        while (h.next != null) {
            h = h.next;
            pos++;
            zs[pos] = h.data;
        }
        System.out.println("in reverse---" + Arrays.toString(zs));
        // now zs has all the elements of this linked list.
        h = head;
        for (int i = zs.length - 1; i >= 0; --i) {
            // like add(zs[i]);
            Node<Z> node = new Node<>();
            node.data = (Z) zs[i];
            node.next = null;
            h.next = node;
            h = h.next;
        }
    }

    public void listReverse() {
        // _ 3 8 9 7 6
        // + 8 3
        Node<Z> rh = new Node<>();
        Node<Z> next;
        Node<Z> cur = head.next;
        while (cur != null) {
            // System.out.println("--- " + cur.data);
            next = cur.next;
            cur.next = rh.next;
            rh.next = cur;
            cur = next; // move origin linked list
        }
        head.next = rh.next;
    }

    /**
     * @param order 0== no sort; 1== 3,2,1 , -1 == 1,2,3.
     */
    public <T extends Comparable<T>> LinkedList<T> merge(LinkedList<T> another, int order) {
        LinkedList<T> list = new LinkedList<>();
        if (0 == order) {
            for (int i = 0; i < size(); ++i) {
                list.addLast((T) get(i));
            }
            if (another != null) {
                for (int i = 0; i < another.size(); ++i) {
                    list.addLast(another.get(i));
                }
            }
        } else {
            for (int i = 0; i < size(); ++i) {
//                list.addLast((T) get(i));
                T data = (T) get(i);
                int j;
                for (j = 0; j < list.size(); ++j) {
                    T z = list.get(j);
                    if (order < 0
                            ? z.compareTo(data) > 0 :
                            z.compareTo(data) < 0) {
                        break;
                    }
                }
                list.insert(j, data);
            }
            if (another != null) {
                for (int i = 0; i < another.size(); ++i) {
                    T data = another.get(i);
                    int j;
                    for (j = 0; j < list.size(); ++j) {
                        T z = list.get(j);
                        if (order < 0
                                ? z.compareTo(data) > 0 :
                                z.compareTo(data) < 0) {
                            break;
                        }
                    }
                    list.insert(j, data);
                }
            }
        }
        return list;
    }

    public String format() {
        int pos = -1;
        StringBuilder sb = new StringBuilder(getClass().getSimpleName() + ": {");
        Node<Z> h = head;
        while (h != null) {
            Z data = h.data;
            if (pos != -1) {
                sb.append("[").append(pos).append("]=").append(data).append(", ");
            }
            h = h.next;
            pos++;
        }
        int last = sb.lastIndexOf(", ");
        if (last != -1) {
            sb.delete(last, last + 2);
        }
        sb.append("} | size=").append(length).append(" ##|");
        return sb.toString();
    }

    public void show() {
        System.out.println(format());
    }

    @Override
    public String toString() {
        return new StringJoiner(", ",
                LinkedList.class.getSimpleName() + "[", "]")
                .add(format()).toString();
    }

    public static void main(String[] args) {
        // big();
        LinkedList<Integer> list = new LinkedList<>();
        Random random = new Random(189);
        for (int i = 0; i < 5; ++i) {
            int data = random.nextInt(100);
            int pos;
            for (pos = 0; pos < list.size(); ++pos) {
                Integer value = list.get(pos);
                if (value > data) {
                    break;
                }
            }
            list.insert(pos, data);
            // System.out.println("each insert: " + list.format());
        }
        System.out.println("self : " + list);
        // list.reverse();
        // System.out.println("reversed--- " + list);

        list.listReverse();
        System.out.println("list-reverse:" + list);
        LinkedList<Integer> integerLinkedList = new LinkedList<>();
        for (int i = 0; i < 3; ++i) {
            integerLinkedList.add(random.nextInt(55));
        }
        System.out.println(integerLinkedList);
        LinkedList<Integer> merge = list.merge(integerLinkedList, -1);
        System.out.println("merged: " + merge);
    }

    private static void big() {
        LinkedList<Integer> list = new LinkedList<>();
        list.show();
        Random random = new Random();
        list.add(random.nextInt(100));
        list.show();
        list.add(random.nextInt(100));
        list.addLast(random.nextInt(100));
        list.show();
        list.removeLast();
        list.show();
        list.removeFirst();
        list.show();
        boolean insert = list.insert(8, random.nextInt(100));
        System.out.println("insert=" + insert + "," + list.format());
        list.clear();
        System.out.println("cleared? " + list.format());
        for (int i = 0; i < 5; ++i) {
            list.addLast(random.nextInt(100));
        }
        list.show();
        list.set(0, -1024);
        list.set(3, 1024);
        list.set(4, -2048);
        list.show();
        list.clear();
        System.out.println("##############");
        for (int i = 0; i < 5; ++i) {
            int data = random.nextInt(300);
            int pos;
            for (pos = 0; pos < list.size(); ++pos) {
                Integer value = list.get(pos);
                if (value > data) {
                    break;
                }
            }
            list.insert(pos, data);
            System.out.println("each insert: " + list.format());
        }
        list.show();

        list.insert(3, 99);
        int index = list.indexOf(99);
        System.out.println("index==" + index);
        list.show();
        list.remove((Integer) 99);
        list.set(2, 345);
        list.show();
        boolean replace = list.replace(2, -544);
        System.out.println("replace--" + replace + " , " + list);
        System.out.println("$$$$: " + list);
    }
}

然后说一下这个反转的思路。

先看一下反转的实现:

    public void listReverse() {
        // _ 3 8 9 7 6
        // + 8 3
        Node<Z> rh = new Node<>();
        Node<Z> next;
        Node<Z> cur = head.next;
        while (cur != null) {
            // System.out.println("--- " + cur.data);
            next = cur.next;
            cur.next = rh.next;
            rh.next = cur;
            cur = next; // move origin linked list
        }
        head.next = rh.next;
    }

反转的代码并不多,直接分析一下这里的实现思路:

  1. 因为是单链表,所以,只能去单向的遍历;那反转的话,就是相当于把链表的连接方向反转一下。大体上,可以认为是,将遍历取出来的节点依次插入到一个空节点的后面,每次都是插入到这个位置,这样,这个空节点形式的链表就是反转之后的链表了。
  2. 具体实现大概是:
    • 先定义一个临时的节点作为反转时的头结点;然后遍历这个单链表,然后就可以拿到每个节点了。拿到这个节点呢,就把这个节点直接插入到临时头结点的后面。
    • 不过,要注意,首先,既然是遍历这个链表,就要去不断的执行 cur = cur.next这样的代码;但是,这个 cur,我们要重新定义它的链接,要把它放到这个临时头结点的后面去,就要尽早的切断 cur跟原链表直接的链接关系。这个切断很简单,直接就是通过局部变量 next = cur.next; ...; cur = next; 这样的方式就可以了。
    • 那么,在 ... 里面,就要去把这个 cur 插入到这个临时头结点的后面去了;同时还得注意,如果只是每次都把 cur 插入到临时头结点的后面,那么,这个临时头结点形成的链表只会有一个元素,这个元素就是不断刷新的 cur;
    • 所以,在把这个cur插入到临时头结点后面的同时,要处理好 cur.next 的指向,这个指向呢因为是遍历的单链表,其实很不好处理,因为你不知道 cur.prev 是什么;
    • 不过因为这个临时头结点 rh的存在,rh.next 一定是上一个 cur,所以,直接先让cur.next 指向 rh.next 然后再把 rh.next 更新成新的cur; 这样一来,通过遍历原始的链表就可以做到每次得到的节点都被插入到临时头结点之后,并且链接到临时头结点原来的下一个节点之前。
    • 最后,遍历结束了,这个rh其实就是反转之后的链表了;这时候让原始的头结点链接到rh的下一个节点,这个原始的链表就被反转完成了。这个rh 也就不再需要了。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值