链表

单链表


代码实现

package com.dy.xidian;

public class LinkedTable<E> {

    private Node head;
    private Node tail;

    // 创建一个空的头节点,头结点中不保存任何数据
    public LinkedTable() {
        head = new Node<E>();
        head.data = null;
        head.next = null;
        tail = head;
    }

    static class Node<E> {
        public E data;
        public Node next;
    }

    private <E> boolean insertHead(E e) {
        Node<E> temp = new Node<>();
        temp.data = e;
        temp.next = head.next;
        head.next = temp;
        return true;
    }

    public <E> boolean insertTail(E e) {
        Node<E> temp = new Node<>();
        temp.data = e;
        temp.next = null;
        tail.next = temp;
        tail = temp;
        return true;
    }

    //获取指定位置的节点
    private Node getNode(int i) {
        int j = 1;
        // p指向链表中的第一个节点(非head)
        Node p = this.head.next;
        if (i < 0)
            return null;
        if (i == 0)
            return head;
        while (p != null && j < i) {
            p = p.next;
            j++;
        }
        return p;
    }
    
    //获取指定位置的元素
    public <E> E getElem(int i) {
        if (i <= 0)
            return null;
        Node<E> node = getNode(i);
        return node.data;
    }

    //在指定位置插入节点
    public boolean insert(int i, E e) {
        if (i <= 0)
            return false;
        Node node = getNode(i - 1);
        Node<E> temp = new Node<>();
        temp.data = e;
        temp.next = node.next;
        node.next = temp;
        return true;
    }

    //删除指定位置节点
    public <E> boolean delete(int i) {
        if (i <= 0)
            return false;
        Node p = getNode(i - 1);
        Node<E> q = p.next;
        p.next = q.next;
        q.data = null;
        q.next = null;
        return true;
    }

    public static void main(String[] args) {
        LinkedTable<String> list = new LinkedTable<>();
        list.insertTail(new String("hello1"));
        list.insertTail(new String("hello2"));
        list.insertTail(new String("hello3"));
        list.insert(2, new String("hello insert"));
        for (int i = 1; i < 5; i++) {
            System.out.println(list.getElem(i));
        }
        System.out.println("---------------------");
        list.delete(3);
        for (int i = 1; i < 4; i++) {
            System.out.println(list.getElem(i));
        }
    }
}

 双链表


 

双链表中一个节点不仅指向他的后继节点还需指向他的前驱节点。

package com.dy.xidian;

import java.util.Hashtable;

public class LinkedTable<E> {

    private Node head;
    private Node tail;

    // 创建一个空的头节点,头结点中不保存任何数据
    public LinkedTable() {
        head = new Node<E>();
        head.data = null;
        head.next = null;
        head.prev = null;
        tail = head;
    }

    static class Node<E> {
        public E data;
        public Node next;
        public Node prev;
    }

    private <E> boolean insertHead(E e) {
        Node<E> temp = new Node<>();
        temp.data = e;
        temp.next = head.next;
        if(head.next != null)
            head.next.prev = temp;
        temp.prev = head;
        head.next = temp;
        return true;
    }
    
    //链表初始化时使用来批量插入节点
    public <E> boolean insertTail(E e) {
        Node<E> temp = new Node<>();
        temp.data = e;
        temp.next = null;
        tail.next = temp;
        temp.prev = tail;
        tail = temp;
        return true;
    }

    // 获取指定位置的节点
    private Node getNode(int i) {
        int j = 1;
        // p指向链表中的第一个节点(非head)
        Node p = this.head.next;
        if (i < 0)
            return null;
        if (i == 0)
            return head;
        while (p != null && j < i) {
            p = p.next;
            j++;
        }
        return p;
    }

    // 获取指定位置的元素
    public <E> E getElem(int i) {
        if (i <= 0)
            return null;
        Node<E> node = getNode(i);
        return node.data;
    }

    // 在指定位置插入节点
    public boolean insert(int i, E e) {
        if (i <= 0)
            return false;
        Node node = getNode(i - 1);
        Node<E> temp = new Node<>();
        temp.data = e;
        temp.next = node.next;
        node.next.prev = temp;
        temp.prev = node;
        node.next = temp;
        return true;
    }

    // 删除指定位置节点
    public <E> boolean delete(int i) {
        if (i <= 0)
            return false;
        Node node = getNode(i - 1);
        Node<E> q = node.next;
        node.next = q.next;
        q.next.prev = node;
        q.data = null;
        q.prev = null;
        q.next = null;
        return true;
    }

    public static void main(String[] args) {
        LinkedTable<String> list = new LinkedTable<>();
        list.insertTail(new String("hello1"));
        list.insertTail(new String("hello2"));
        list.insertTail(new String("hello3"));
        list.insert(2, new String("hello insert"));
        for (int i = 1; i < 5; i++) {
            System.out.println(list.getElem(i));
        }
        System.out.println("---------------------");
        list.delete(3);
        for (int i = 1; i < 4; i++) {
            System.out.println(list.getElem(i));
        }
    }
}

循环链表与循环双链表


 

循环链表与单链表的区别是是将最后一个节点指向头节点,而循环双链表是将双链表与循环链表结合使用。

顺序表和链表的比较


 

存储规模无法估计时使用链表,查找频繁使用顺序表,插入频繁使用链表。

链表的应用


 

  •  链表的逆置(创建一个头节点,每次从原链表中取一个节点,采用头插法的方式插入到新链表中去)
  • 链表排序(使用直接插入排序算法)
  • 找出两个链表的公共节点(如果两个链表有公共节点,那么这两个链表的形状看起来是个Y。如果这两个链表一样长,那么同时遍历两个链表会同时到达公共点。)
  • 已知链表A和B分别为两个集合,其元素递增。编写函数求A与B的交集,并放到链表A中
  • 一个长度为N的整型数组A[1...N],给定整数X,设计一个时间复杂度不超过O(nlogn)的算法,查找出这个数据中所有两两之和等于X的整数对
原文地址:https://www.cnblogs.com/xidongyu/p/5936691.html