一、链表是什么

二、链表的实现原理

 

一、链表是什么

  相比于线性表顺序结构,链表比较方便插入和删除的操作。例如数组当需要存储的数据很庞大时,插入和删除就会比较麻烦。这时候用链表就会方便很多。

  链表是一种物理储存单元上非连续、非顺序的储存结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表是由一系列结点(链表中的每一个元素都称为结点)组成,结点可以在运行时动态生成。每个结点由两个部分组成:一个是存储数据元素的数据域,另一个是储存下一个结点地址的指针域。

  链表有很多种不同的类型:单向链表,双向链表以及循环链表。

    双向链表是单向链表的改进对链表进组操作时,有时要对某一个结点前面的一个结点进行操作时,又必须从表头开始查找,这是单向链表结点结构所限制的。因为单向链表每个结点都只有一个存储直接子节点地址的链域,那么可以定义一个既有存储直接子结点地址的链域,又存储直接父结点地址的链域的这样一个双链域结构,这就是双向链表。

    双向链表结点除了含有数据域外,还有两个链域,一个存储直接子结点地址,称为右链域。一个存储直接父结点地址,一般称为左链域。

 

二、链表的实现原理

    首先定义一个链表的结点类,有了这个结点类就可以实现一个单向链表了。

public class LinkedNode {
    public Object obj;// 结点内的数据对象
    public LinkedNode next;// 对下一个结点的引用

    // 在创建结点对象时,就传入结点中的数据对象
    public LinkedNode(Object obj) {
        this.obj = obj;
    }public Object getobj() {
        return obj;
    }

    public void setobj(Object obj) {
        this.obj = obj;
    }

    public LinkedNode getNext() {
        return next;
    }

    public void setNext(LinkedNode next) {
        this.next = next;
    }

}

  然后实现一个单向的链表

public class Linkedlist {

    // 创建链表的方法
    public LinkedNode createLink() {
        String s = "根节点";
        LinkedNode root = new LinkedNode(s);
        LinkedNode n1 = new LinkedNode("一节点");
        LinkedNode n2 = new LinkedNode("二节点");
        LinkedNode n3 = new LinkedNode("三节点");
        LinkedNode n4 = new LinkedNode("四节点");
        root.setNext(n1);
        n1.setNext(n2);
        n2.setNext(n3);
        n3.setNext(n4);
        return root;
    }

    // 遍历链表的方法
    public void printLinkedLinst(LinkedNode root) {
        if (null != root) {
            Object data = root.getobj();
            System.out.println(data);
            LinkedNode temp = root.getNext();
            printLinkedLinst(temp);
        }
    }

    // 主方法
    public static void main(String[] args) {
        Linkedlist list = new Linkedlist();
        // 创建链表
        LinkedNode root = list.createLink();
        // 遍历
        list.printLinkedLinst(root);
    }

}

运行一下

根节点
一节点
二节点
三节点
四节点

  对链表的使用:最基本的使用就是实现数据的查找、插入、删除、合并、等简单的操作。

  下面实现,获取、放置、添加、插入、删除等的方法。

  首先定义一个链表结点类

public class LinkedNode<E> {
    private Object obj;// 结点内的数据对象
    private LinkedNode<E> next;// 对下一个结点的引用
    private LinkedNode<E> befor;// 对上一个结点的引用

    // 在创建结点对象时,就传入结点中的数据对象
    public LinkedNode(Object obj) {

        this.obj = obj;
    }

    public LinkedNode() {

    }

    public LinkedNode<E> getBefor() {
        return befor;
    }

    public void setBefor(LinkedNode<E> befor) {
        this.befor = befor;
    }

    public Object getobj() {
        return obj;
    }

    public void setobj(Object obj) {
        this.obj = obj;
    }

    public LinkedNode<E> getNext() {
        return next;
    }

    public void setNext(LinkedNode<E> next) {
        this.next = next;
    }

}

然后创建一个链表实现自定义队列类

public class Linkedlist<E> {

    private LinkedNode<E> root = new LinkedNode<E>();
    private LinkedNode<E> last;// 最后一个结点
    private int size;

    public int size() {
        return size;
    }

    // 检差下标index 是否越界的方法
    private void checkIndex(int index) {
        if (index < 0 || index > size) {// 越界报错
            System.out.println("下标:" + index + "越界啦");
        }
    }

    // 获取结点元素的方法
    public E get(int index) {
        // 检差下标是否越界
        checkIndex(index);
        LinkedNode<E> node = root.getNext();
        // 遍历找到下标为index的结点
        for (int i = 0; i < index; i++) {
            node = node.getNext();
        }
        return (E) node.getobj();
    }

    // 放置结点元素的方法
    public void set(int index, E e) {
        // 检差下标是否越界
        checkIndex(index);
        LinkedNode<E> node = root.getNext();
        // 遍历找到下标为index的结点
        for (int i = 0; i < index; i++) {
            node = node.getNext();
        }
        node.setobj(e);

    }

    // 向链表添加结点的方法
    public void add(E e) {

        LinkedNode<E> node = new LinkedNode<E>(e);
        if (size == 0) {// 如果是第一个节点
            root.setNext(node);// 添加到空节点后面
            last = node;// 更新最后一个节点
            size++;
        } else {
            last.setNext(node);// 添加到最后一个节点后面
            last = node;// 更新最后一个节点
            size++;
        }
    }

    // 插入结点的办法
    public void insert(int index, E e) {
        // 检查下标是否越界
        checkIndex(index);
        // 找到下标为index的节点
        LinkedNode<E> node = root.getNext();
        for (int i = 0; i < index; i++) {
            node = node.getNext();
        }
        LinkedNode<E> node1 = new LinkedNode<E>(e);
        if (index == 0) {// 如果要插入在最前面
            root.setNext(null);// 断开空节点和第一个节点
            root.setNext(node1);// 空节点指向新节点
            node1.setNext(node);// 新节点指向原第一个节点

        } else {
            // 找到下标为index节点的前一个节点
            LinkedNode<E> node2 = root.getNext();
            for (int i = 0; i < index - 1; i++) {
                node2 = node2.getNext();
            }
            node2.setNext(null);// 断开前一个节点
            node2.setNext(node1);
            node1.setNext(node);
        }
        size++;
    }

    // 删除链表结点的方法
    public void remove(int index) {
        // 检查下标是否越界
        checkIndex(index);
        LinkedNode<E> node = root.getNext();
        if (index != 0) {// 如果不是第一个节点
            for (int i = 0; i < index - 1; i++) {// 找到下标为index-1,既前一个的节点
                node = node.getNext();
            }
            LinkedNode<E> node1 = node.getNext();// 找到下标为index的节点
            if (index != size - 1) {// 如果不是最后一个节点
                LinkedNode<E> node2 = node1.getNext();// 下标index的下一个节点
                node.setNext(null);// 断开前一个节点和index节点
                node.setNext(node2);// 将前一个节点指向后一个节点
            } else {// 是最后一个节点
                node.setNext(null);// 断开前一个节点和index节点
            }
            node1.setobj(null);// 删除节点存贮的内容
            node1.setNext(null);// 删除index节点指向
        } else {// 移除第一个节点
            LinkedNode<E> node4 = root.getNext();
            LinkedNode<E> node5 = node4.getNext();
            root.setNext(null);
            root.setNext(node5);
            node4.setNext(null);
        }
        size--;
    }

    // 遍历链表的方法
    public static void printLinkedLinst(Linkedlist list) {
        for (int i = 0; i < list.size; i++) {
            System.out.print("  " + list.get(i));
        }
        System.out.println(" ");
    }

    // 主方法
    public static void main(String[] args) {
        Linkedlist<String> list = new Linkedlist<String>();
        // 向链表添加结点
        list.add("添加1");
        list.add("添加2");
        list.add("添加3");
        list.add("添加4");
        list.add("添加5");
        list.add("添加6");
        list.add("添加7");
        list.add("添加8");
        System.out.println("---添加后");
        printLinkedLinst(list);

        list.set(2, "放置2");
        list.set(3, "放置3");
        System.out.println("---放置后");
        printLinkedLinst(list);

        int get = 2;// 获取的节点的下标
        System.out.println("---获取结点的下标为:" + get + ",结点内容为:");
        System.out.println(list.get(get));

        list.insert(4, "插入4");
        System.out.println("---插入后");
        printLinkedLinst(list);

        // 删除位置
        int rem = 6;
        list.remove(rem);
        System.out.println("---删除位置下标:" + rem + "   " + "删除后 ");
        printLinkedLinst(list);

    }

}

运行一下

---添加后
  添加1  添加2  添加3  添加4  添加5  添加6  添加7  添加8 
---放置后
  添加1  添加2  放置2  放置3  添加5  添加6  添加7  添加8 
---获取结点的下标为:2,结点内容为:
放置2
---插入后
  添加1  添加2  放置2  放置3  插入4  添加5  添加6  添加7  添加8 
---删除位置下标:6   删除后 
  添加1  添加2  放置2  放置3  插入4  添加5  添加7  添加8 

 

 

 

 

posted on 2019-02-19 16:36  张裕泉  阅读(134)  评论(0编辑  收藏  举报