数据结构-链表

博客 动态
0 265
羽尘
羽尘 2022-01-25 21:54:32
悬赏:0 积分 收藏

数据结构-链表

链表

现虽然顺序表的查询很快,时间复杂度为 O(1) , 但是增删的效率是比较低的,因为每一次增删操作都伴随着大量的数据元素移动。

所以可以使用另外一种存储结构实现线性表,链式存储结构。

链表是一种物理存储单元上非连续、非顺序的存储结构,其物理结构不能只管的表示数据元素的逻辑顺序,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列的结点(链表中的每一个元素称为结点)组成,结点可以在运行时动态生成。

123

1.单向链表

单向链表是链表的一种,它由多个结点组成,每个结点都由一个数据域一个指针域组成,数据域用来存储数据,指针域用来指向其后继结点

链表的头结点的数据域不存储数据,指针域指向第一个真正存储数据的结点。

4

1.1 单链表实现

public class LinkList<T> implements Iterable<T> {    //记录头节点    private Node head;    //记录元素个数    private int n;    public class Node {        //存储元素        public T item;        //指向下一个结点        public Node next;        public Node(T item, Node next) {            this.item = item;            this.next = next;        }    }    //构造函数    public LinkList() {        //初始化头节点        this.head = new Node(null, null);        //初始化个数        this.n = 0;    }    //清空链表    public void clear() {        this.head = null;        this.n = 0;    }    //获取链表的长度    public int length() {        return n;    }    //判断链表是否为空    public boolean isEmpty() {        return n == 0;    }    //获取指定位置i出的元素    public T get(int i) {        Node m = head.next;        //通过头结点,循环往后找到第i个元素        for (int j = 0; j < i; j++) {            m = m.next;        }        return m.item;    }    //向链表中添加元素t    public void insert(T t) {        //找到当前最后一个结点        Node m = head;        while (m.next != null) {            m = m.next;        }        //创建新节点,值为t        Node tNode = new Node(t, null);        //最后一个元素指向新节点        m.next = tNode;        //元素个数+1        n++;    }    //向指定位置i出,添加元素t    public void insert(int i, T t) {        //找出i之前的结点        Node pre = this.head;        for (int j = 0; j < i; j++) {            pre = pre.next;        }        //指向i结点        Node curr = pre.next;        //创建结点,值为t,指向curr        Node node = new Node(t, curr);        //i之前的结点pre,指向node        pre.next = node;        //元素数+1        n++;    }    //删除指定位置i处的元素,并返回被删除的元素    public T remove(int i) {        //找到i位置的前一个节点        Node pre = head;        for (int index = 0; index <= i - 1; i++) {            pre = pre.next;        }        //要找到i位置的结点        Node curr = pre.next;        //找到i位置的下一个结点        Node nNode = curr.next;        //前一个结点指向下一个结点        pre.next = nNode;        //元素个数-1        n--;        return curr.item;    }    //查找元素t在链表中第一次出现的位置    public int indexOf(T t) {        //从头结点开始,依次找到每一个结点,取出item,和t比较,如果相同,就找到了        Node n = head;        for (int i = 0; n.next != null; i++) {            n = n.next;            if (n.item.equals(t)) {                return i;            }        }        return -1;    }    @Override    public Iterator<T> iterator() {        return new Literator();    }    public class Literator implements Iterator{        private Node n;        public Literator(){            this.n=head;        }        @Override        public boolean hasNext() {            return n.next!=null;        }        @Override        public Object next() {            n = n.next;            return n.item;        }    }}

1.2 单链表测试

public static void main(String[] args) {    //创建单向链表对象    LinkList<String> sl = new LinkList<>();    //测试插入    sl.insert("T1");    sl.insert("T2");    sl.insert("T3");    sl.insert(1, "T4");    for (String s : sl) {        System.out.println(s);    }    System.out.println("------------------------------------------");    //测试获取    String getResult = sl.get(1);    System.out.println("获取索引1处的结果为:" + getResult);    //测试删除    String removeResult = sl.remove(0);    System.out.println("删除的元素是:" + removeResult);    //测试清空    sl.clear();    System.out.println("清空后的线性表中的元素个数为:" + sl.length());}

4

2.双向链表

双向链表也叫双向表,是链表的一种,它由多个结点组成,每个结点都由一个数据域两个指针域组成,数据域用来存储数据,其中一个指针域用来指向其后继结点,另一个指针域用来指向前驱结点。

链表的头结点的数据域不存储数据,指向前驱结点的指针域值为null,指向后继结点的指针域指向第一个真正存储数据的结点。

6

2.1 双向链表实现

public class TowWayLinkList<T> implements Iterable<T> {    //首结点    private Node head;    //尾结点    private Node last;    //元素总个数    private int n;    private class Node {        //存储数据        public T item;        //指向上一个结点        public Node pre;        //指向下一个结点        public Node next;        public Node(T item, Node pre, Node next) {            this.item = item;            this.pre = pre;            this.next = next;        }    }    //初始化    public TowWayLinkList() {        //初始化首结点        this.head = new Node(null, null, null);        //初始化尾结点        this.last = null;        //初始化元素个数        this.n = 0;    }    //清空链表    public void clear() {        this.head.next = null;        this.head.pre = null;        this.head.item = null;        this.last = null;        this.n = 0;    }    //获取链表长度    public int length() {        return n;    }    //判断链表是否为空    public boolean isEmpty() {        return n == 0;    }    //获取第一个元素    public T getFirst() {        if (isEmpty()) {            return null;        }        return head.next.item;    }    //获取最后一个元素    public T getLast() {        if (isEmpty()) {            return null;        }        return last.item;    }    //插入元素t    public void insert(T t) {        //链表为空        if (isEmpty()) {            //创建新结点            Node nNode = new Node(t, head, null);            //让新结点成为尾结点            last = nNode;            //让头结点指向尾结点            head.next = last;        } else {            //链表不为空            Node oldLast = last;            //创建新结点            Node nNode = new Node(t, oldLast, null);            //让当前尾结点指向新结点            oldLast.next = nNode;            //让新结点成为尾结点            last = nNode;        }        //元素个数+1        n++;    }    //向指定位置i处插入元素t    public void insert(int i, T t) {        //找到i位置的前一个结点        Node pre = head;        for (int index = 0; index < i; index++) {            pre = pre.next;        }        //找到i位置的结点        Node curr = pre.next;        //创建新结点        Node nNode = new Node(t, pre, curr);        //让i位置的前一个结点的下一个结点指向新结点        pre.next = nNode;        //让i位置的前一个结点变为新结点        curr.pre = nNode;        //元素个数+1        n++;    }    //获取指定位置i处的元素    public T get(int i) {        Node n = head.next;        for (int index = 0; index < i; index++) {            n = n.next;        }        return n.item;    }    //找到元素t在链表中第一次出现的位置    public int indexOf(T t) {        Node n = head;        for (int i = 0; n.next != null; i++) {            n = n.next;            if (n.item.equals(t)) {                return i;            }        }        return -1;    }    //删除位置i处的元素,并返回该元素    public T remove(int i) {        //找到i位置的前一个结点        Node pre = head;        for (int index = 0; index<i; index++) {            pre = pre.next;        }        //找到i位置的结点        Node curr = pre.next;        //找到i位置的下一个结点        Node nNode = curr.next;        //i位置的前一个结点 的下一个结点 指向 i位置的下一个结点 的 前一个结点        pre.next = nNode;        //i位置的下一个结点 的前一个结点 指向 i位置的上一个结点 的 下一个结点        nNode.pre = pre;        //元素个数-1        n--;        return curr.item;    }    @Override    public Iterator<T> iterator() {        return new tIterator();    }    public class tIterator implements Iterator {        private Node node;        public tIterator() {            this.node = head;        }        @Override        public boolean hasNext() {            return node.next != null;        }        @Override        public Object next() {            node=node.next;            return node.item;        }    }}

2.2 双向链表测试

public static void main(String[] args) {    //创建双向链表对象    TowWayLinkList<String> sl = new TowWayLinkList<>();    //测试插入    sl.insert("T1");    sl.insert("T2");    sl.insert("T3");    sl.insert(1, "T4");    for (String s : sl) {        System.out.println(s);    }    System.out.println("--------------------------------------");        System.out.println("第一个元素是:" + sl.getFirst());    System.out.println("最后一个元素是:" + sl.getLast());        System.out.println("------------------------------------------");    //测试获取    String getResult = sl.get(1);    System.out.println("获取索引1处的结果为:" + getResult);    //测试删除    String removeResult = sl.remove(0);    System.out.println("删除的元素是:" + removeResult);    //测试清空    sl.clear();    System.out.println("清空后的线性表中的元素个数为:" + sl.length());}
7

3.循环链表

循环链表,链表整体要形成一个圆环状。在单向链表中,最后一个节点的指针为null,不指向任何结点,因为没有下一个元素了。

实现循环链表,只需要让单向链表的最后一个节点的指针指向头结点即可。

8

简单构建

public class CircularLinkedList {    public static class Node<T> {        T item;        Node<T> next;        public Node(T item, Node next) {            this.item = item;            this.next = next;        }    }    public static void main(String[] args) throws Exception {        //构建结点        Node<Integer> first = new Node<Integer>(1, null);        Node<Integer> second = new Node<Integer>(2, null);        Node<Integer> third = new Node<Integer>(3, null);        Node<Integer> fourth = new Node<Integer>(4, null);        Node<Integer> fifth = new Node<Integer>(5, null);        Node<Integer> six = new Node<Integer>(6, null);        Node<Integer> seven = new Node<Integer>(7, null);        //构建单链表        first.next = second;        second.next = third;        third.next = fourth;        fourth.next = fifth;        fifth.next = six;        six.next = seven;        //构建循环链表,让最后一个结点指向第一个结点        seven.next = first;    }}

个人博客为:
MoYu's HomePage

posted @ 2022-01-25 20:46 MoYu-zc 阅读(1) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员