《java数据结构》--链表

来源:互联网 发布:c语言程序编程教学 编辑:程序博客网 时间:2024/05/20 20:02

java数据结构

参考:数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现

主要有以下几种类型

  • 单向链表
  • 双端链表
  • 有序链表
  • 双向链表
  • 有迭代器的链表

链表的效率

这里顺便谈下链表和数组相比效率的优越性.在表头插入和删除的速度都很快,因为只需要改变一下引用所以花费O(1)的时间.平均起来查找,删除和在指定节点后插入数据都需要搜索一半的链结点.需要O(N)次比较和数组一样.然由于链表删除插入的时候不需要像数组那种元素的移动.所以效率还是要优于数组.还有一点就是链表的内存可以随时的扩展内存.而数组的内存是一开始就固定好的.这样就会导致数组的效率和可用性大大下降.链表劣势在于随机访问,无法像数组那样直接通过下标找到特定的数据项 

java代码实现

单向链表

image

package cn.zlz.structure;/** * 单向链表 持有一个首部节点,可以实现栈,后进先出 */public class LinkedList<V> {    // 链表头部    private Node first;    // 长度    private int size;    public LinkedList() {        super();    }    // 首部插入新的节点    public Node<V> insertFirst(V value) {        Node<V> node = new Node<V>(value);        // 新节点的next指向老节点        node.setNext(first);        first = node;        // 长度+1        size++;        return node;    }    // 获取指定位置节点    public Node<V> get(int index) {        if (this.isEmpty()) {            throw new IndexOutOfBoundsException("链表为空");        }        if (index >= size) {            throw new IndexOutOfBoundsException("越界");        }        Node node = first;        while (index-- > 0) {            node = node.getNext();        }        return node;    }    // 删除指定位置节点    public Node<V> remove(int index) {        if (this.isEmpty()) {            throw new IndexOutOfBoundsException("链表为空");        }        if (index >= size) {            throw new IndexOutOfBoundsException("越界");        }        // 待删除节点        Node<V> removeNode = null;        // 待删除节点的上个节点        Node<V> pre = null;        if (index == 0) {            // 没有上个节点            pre = null;            removeNode = first;            first = removeNode.next;        } else {            pre = this.get(index - 1);            // 已通过长度验证pre.next存在            removeNode = pre.next;            pre.next = removeNode.next;        }        if (--size <= 0) {            first = null;        }        return removeNode;    }    // 判断linkList是否为空    public boolean isEmpty() {        return first == null;    }    // 获取链表长度    public int getSize() {        return size;    }    @Override    public String toString() {        if (first == null) {            return "LinkedList ";        }        return "LinkedList [" + first.toString() + "]";    }    // 节点类    class Node<V> {        private V value;        private Node next;        public Node() {            super();        }        public Node(V value) {            super();            this.value = value;        }        public V getValue() {            return value;        }        public void setValue(V value) {            this.value = value;        }        public Node getNext() {            return next;        }        public void setNext(Node next) {            this.next = next;        }        @Override        public String toString() {            return "Node [value=" + value + ", next=" + next + "]";        }    }    // 测试    public static void main(String[] args) {        LinkedList<String> linkedList = new LinkedList<String>();        linkedList.insertFirst("a");        linkedList.insertFirst("b");        linkedList.insertFirst("c");        linkedList.insertFirst("d");        linkedList.insertFirst("e");        linkedList.insertFirst("f");        System.out.println(linkedList.toString());        LinkedList<String>.Node<String> node = linkedList.get(2);        System.out.println(node.getValue());        LinkedList<String>.Node<String> removeNode = linkedList.remove(0);        System.out.println(linkedList.toString());        System.out.println(node.getValue());    }}

双端单向链表

image

package cn.zlz.structure;/** * 双端单向链表 持有一个首部节点引用和尾部节点引用,可以实现队列,先进先出 *  * 双端链表与传统链表非常相似.只是新增了一个属性-即对最后一个链结点的引用,单向链表只能从首部开始操作,双端链表首尾都可以 */public class DbPortLinkedList<V> {    // 链表头部    private Node first;    // 链表尾部    private Node last;    // 长度    private int size;    public DbPortLinkedList() {        super();    }    // 首部添加新的节点    public Node<V> insertFirst(V value) {        Node<V> node = new Node<V>(value);        // 新节点的next指向老节点        if (this.isEmpty()) {            last = node;        }        node.setNext(first);        first = node;        // 长度+1        size++;        return node;    }    // 尾部添加新的节点    public Node<V> insertLast(V value) {        Node<V> node = new Node<V>(value);        // 新节点的next指向老节点        if (this.isEmpty()) {            first = node;            last = node;            return node;        }        last.setNext(node);        last = node;        // 长度+1        size++;        return node;    }    // 获取指定位置节点    public Node<V> get(int index) {        if (this.isEmpty()) {            throw new IndexOutOfBoundsException("链表为空");        }        if (index >= size) {            throw new IndexOutOfBoundsException("越界");        }        Node node = first;        while (index-- > 0) {            node = node.getNext();        }        return node;    }    // 删除指定位置节点    public Node<V> remove(int index) {        if (this.isEmpty()) {            throw new IndexOutOfBoundsException("链表为空");        }        if (index >= size) {            throw new IndexOutOfBoundsException("越界");        }        // 待删除节点        Node<V> removeNode = null;        // 待删除节点的上个节点        Node<V> pre = null;        if (index == 0) {            // 没有上个节点            pre = null;            removeNode = first;            first = removeNode.next;        } else {            pre = this.get(index - 1);            // 已通过长度验证pre.next存在            removeNode = pre.next;            pre.next = removeNode.next;        }        // 长度-1,并验证链表是否为空        if (--size <= 0) {            first = null;            last = null;        }        return removeNode;    }    // 判断linkList是否为空    public boolean isEmpty() {        return first == null && last == null;    }    // 获取链表长度    public int getSize() {        return size;    }    @Override    public String toString() {        if (first == null) {            return "DbPortLinkedList ";        }        return "DbPortLinkedList [" + first.toString() + "]";    }    // 节点类    class Node<V> {        private V value;        private Node next;        public Node() {            super();        }        public Node(V value) {            super();            this.value = value;        }        public V getValue() {            return value;        }        public void setValue(V value) {            this.value = value;        }        public Node getNext() {            return next;        }        public void setNext(Node next) {            this.next = next;        }        @Override        public String toString() {            return "Node [value=" + value + ", next=" + next + "]";        }    }    // 测试    public static void main(String[] args) {        DbPortLinkedList<String> dbPortLinkedList = new DbPortLinkedList<String>();        dbPortLinkedList.insertFirst("a");        dbPortLinkedList.insertFirst("b");        dbPortLinkedList.insertLast("c");        dbPortLinkedList.insertFirst("d");        dbPortLinkedList.insertLast("e");        dbPortLinkedList.insertFirst("f");        System.out.println(dbPortLinkedList.toString());        DbPortLinkedList<String>.Node<String> node = dbPortLinkedList.get(2);        System.out.println(node.getValue());        DbPortLinkedList<String>.Node<String> removeNode = dbPortLinkedList.remove(0);        System.out.println(dbPortLinkedList.toString());        System.out.println(removeNode.getValue());    }}

有序链表

package cn.zlz.structure;/** * 有序单向链表:链表中的数据按从小到大排列 持有一个首部节点 * 有序链表插入数据效率为O(N),但查找跟删除最大数据就是表头数据效率为O(1).所以在最小数据存储频繁,但又不需要快速插入的时候有序链表是个不错的选择. */public class SortedLinkedList {    // 链表头部    private Node first;    // 长度    private int size;    public SortedLinkedList() {        super();    }    // 首部插入新的节点    public Node insertFirst(Integer value) {        Node node = new Node(value);        // 查找位置,即找到前面一个节点和后面一个节点        Node pre = null;//插入位置前面节点        Node current = first;//插入位置后面节点        while (current != null && current.getValue()<value) {            pre = current;            current=current.next;        }        //最小的,插在第一个位置        if(pre == null){            first = node;        }else{            pre.next = node;        }        //新插入的节点不管怎么next都指向当前节点        node.next = current;        // 长度+1        size++;        return node;    }    // 获取指定位置节点    public Node get(int index) {        if (this.isEmpty()) {            throw new IndexOutOfBoundsException("链表为空");        }        if (index >= size) {            throw new IndexOutOfBoundsException("越界");        }        Node node = first;        while (index-- > 0) {            node = node.getNext();        }        return node;    }    // 删除指定位置节点    public Node remove(int index) {        if (this.isEmpty()) {            throw new IndexOutOfBoundsException("链表为空");        }        if (index >= size) {            throw new IndexOutOfBoundsException("越界");        }        // 待删除节点        Node removeNode = null;        // 待删除节点的上个节点        Node pre = null;        if (index == 0) {            // 没有上个节点            pre = null;            removeNode = first;            first = removeNode.next;        } else {            pre = this.get(index - 1);            // 已通过长度验证pre.next存在            removeNode = pre.next;            pre.next = removeNode.next;        }        if (--size <= 0) {            first = null;        }        return removeNode;    }    // 判断linkList是否为空    public boolean isEmpty() {        return first == null;    }    // 获取链表长度    public int getSize() {        return size;    }    @Override    public String toString() {        if (first == null) {            return "SortedLinkedList ";        }        return "SortedLinkedList [" + first.toString() + "]";    }    // 节点类    class Node {        private int value;        private Node next;        public Node() {            super();        }        public Node(int value) {            super();            this.value = value;        }        public int getValue() {            return value;        }        public void setValue(int value) {            this.value = value;        }        public Node getNext() {            return next;        }        public void setNext(Node next) {            this.next = next;        }        @Override        public String toString() {            return "Node [value=" + value + ", next=" + next + "]";        }    }    // 测试    public static void main(String[] args) {        SortedLinkedList sortedLinkedList = new SortedLinkedList();        sortedLinkedList.insertFirst(4);        sortedLinkedList.insertFirst(2);        sortedLinkedList.insertFirst(3);        sortedLinkedList.insertFirst(5);        System.out.println(sortedLinkedList);    }}

双向链表

image
image
image

package cn.zlz.structure;/** * 双向链表,注意画图来看 * 注意:双向链表需要初始化一个header头,但是这个header头不属于链表的一个元素 */public class DbLinkedList<V> {    // 链表头部    private Node header;    // 长度    private int size;    public DbLinkedList() {        super();        //创建表头        this.header = new Node(null, null, null);        //表头自循环        this.header.next = this.header;        this.header.pre = this.header;    }    // 首部添加新的节点    public Node<V> insert(int index,V value) {        if (index > size) {            throw new IndexOutOfBoundsException("越界");        }        Node<V> current = null ;        if(size == 0){            current = this.header;        }else{            current = get(index);        }        Node<V> node = new Node<V>(value,current.pre,current);        node.pre.next = node;        node.next.pre = node;        // 长度+1        size++;        return node;    }    public Node<V> insertFirst(int index,V value) {        return this.insert(0, value);    }    public Node<V> insertLast(int index,V value) {        //面向对象        Node<V> node = new Node<V>(value,this.header.pre,this.header);        node.pre.next = node;        node.next.pre = node;        // 长度+1        size++;        return node;    }    // 首部添加新的节点    //注意:双向链表中的元素不包括header    public Node<V> get(int index) {        if (size==0 || index > size) {            throw new IndexOutOfBoundsException("越界");        }        Node<V> node = null;        //如果是后半从后往前找        if(index>(size)/2){            System.out.println("从后往前找");            //header不属于链表,所以z最后一个是插入中的一个。            node = this.header.pre;            int round = size-index;            while (round-->=0) {                node = node.pre;            }        }else{//从前往后找            System.out.println("从前往后找");            //header不属于链表,所以第一个是header的next,插入的时候对0单独处理了,执行get的时候至少已经插入一条            node = this.header.next;            while (index-->0) {                node = node.next;            }        }        return node;    }    public Node<V> remove(int index){        if (size==0 || index > size-1) {            throw new IndexOutOfBoundsException("越界");        }        Node<V> toDelNode = this.get(index);        toDelNode.pre.next = toDelNode.next;        toDelNode.next.pre = toDelNode.pre;        size--;        return toDelNode;    }    // 获取链表长度    public int getSize() {        return size;    }    // 判断linkList是否为空    public boolean isEmpty() {        return size == 0;    }    public Node getHeader() {        return header;    }    public void setHeader(Node header) {        this.header = header;    }    public void setSize(int size) {        this.size = size;    }    @Override    public String toString() {        StringBuilder stringBuilder = new StringBuilder();        Node header = this.getHeader();        Node next = header.getNext();        stringBuilder.append(header.getPre().getValue()+":"+header.getValue()+":"+header.getNext().getValue());        while(next!=header){            stringBuilder.append("   ");            stringBuilder.append(next.getPre().getValue()+":"+next.getValue()+":"+next.getNext().getValue());            next = next.next;        }        return stringBuilder.toString();    }    // 节点类    class Node<V> {        private V value;// 值        private Node pre;// 前一个节点        private Node next;// 后一个节点        public Node() {            super();        }        public Node(V value, Node pre, Node next) {            super();            this.value = value;            this.pre = pre;            this.next = next;        }        public Node(V value) {            super();            this.value = value;        }        public V getValue() {            return value;        }        public void setValue(V value) {            this.value = value;        }        public Node getPre() {            return pre;        }        public void setPre(Node pre) {            this.pre = pre;        }        public Node getNext() {            return next;        }        public void setNext(Node next) {            this.next = next;        }        @Override        public String toString() {            return "Node [value=" + value + ", pre=" + pre + ", next=" + next + "]";        }    }    // 测试    public static void main(String[] args) {        DbLinkedList<String> dbLinkedList = new DbLinkedList<String>();        System.out.println(dbLinkedList.toString());        dbLinkedList.insert(0,"a");        System.out.println(dbLinkedList.toString());        dbLinkedList.insert(1,"b");        System.out.println(dbLinkedList.toString());        dbLinkedList.insert(2,"b");        System.out.println(dbLinkedList.toString());        dbLinkedList.insert(1,"c");        System.out.println(dbLinkedList.toString());        dbLinkedList.insert(4,"d");        System.out.println(dbLinkedList.toString());        dbLinkedList.insert(0,"e");        System.out.println(dbLinkedList.toString());        System.out.println(dbLinkedList.get(3).getValue());//      dbLinkedList.insertFirst("f");        System.out.println(dbLinkedList.toString());    }}
0 0
原创粉丝点击