一、链表是什么
二、链表的实现原理
一、链表是什么
相比于线性表顺序结构,链表比较方便插入和删除的操作。例如数组当需要存储的数据很庞大时,插入和删除就会比较麻烦。这时候用链表就会方便很多。
链表是一种物理储存单元上非连续、非顺序的储存结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表是由一系列结点(链表中的每一个元素都称为结点)组成,结点可以在运行时动态生成。每个结点由两个部分组成:一个是存储数据元素的数据域,另一个是储存下一个结点地址的指针域。
链表有很多种不同的类型:单向链表,双向链表以及循环链表。
双向链表是单向链表的改进对链表进组操作时,有时要对某一个结点前面的一个结点进行操作时,又必须从表头开始查找,这是单向链表结点结构所限制的。因为单向链表每个结点都只有一个存储直接子节点地址的链域,那么可以定义一个既有存储直接子结点地址的链域,又存储直接父结点地址的链域的这样一个双链域结构,这就是双向链表。
双向链表结点除了含有数据域外,还有两个链域,一个存储直接子结点地址,称为右链域。一个存储直接父结点地址,一般称为左链域。
二、链表的实现原理
首先定义一个链表的结点类,有了这个结点类就可以实现一个单向链表了。
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