zoukankan      html  css  js  c++  java
  • 快速找到未知长度单链表的中间节点

    在讨论之前,我们首先首先要明白,什么是单链表?

    单链表:链接方式存储的线性表

    单链表的结点结构
      ┌──┬──┐
      │data│next│
      └──┴──┘ 
           data域--存放结点值的数据域
           next域--存放结点的直接后继的地址(位置)的指针域(链域)
    注意:
         ①链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的。
         ②每个结点只有一个链域的链表称为单链表(Single Linked List)。

    那么我们先用java设计一下我们的单链表

    public class MyLinkedList<E> {
        Node<E> first;
        Node<E> last;
    
        public MyLinkedList() {
            super();
        }
    
        public void add(E e) {
            if (first == null) {
                first = new Node<E>(e, null);
            } else {
                if (last == null) {
                    last = new Node<E>(e, null);
                    first.next = last;// 因为first和last还没建立关系,所以在这里要将他们的关系建立起来
                } else {
                    Node<E> n = new Node<>(e, null);// 一个临时的引用n
                    last.next = n;// 将last的next赋值为n的引用
                    last = n;// 然后再将last重新赋值为n的引用
                }
            }
        }
    
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for (Node<E> n = first; n != null; n = n.next) {
                sb.append(n.item).append(",");
            }
            sb.deleteCharAt(sb.length()-1).append("]");
            return sb.toString();
        }
    
        private static class Node<E> {
            E item;
            Node<E> next;
    
            Node(E element, Node<E> next) {
                this.item = element;
                this.next = next;
            }
        }
    }

    注意了,在这里我设计的单链表仅仅是为了符合我们讨论的问题,并不是完整的单链表,同时为了测试,我重写了toString方法。在这个单链表里面,我并没有实现List<E>这个接口,因为要实现的方法太多了,而且first和last这两个成员变量没有用private修饰符修饰,是不符合封装的思想,这里我一切从简。

    我们先往里面添加一些数值,顺便测试下我们设计的单链表是否可以

    public static void main(String[] args){
            MyLinkedList<Integer> list=new MyLinkedList<>();
            list.add(2);
            list.add(1);
            list.add(5);
            list.add(8);
            list.add(7);
            System.out.println(list.toString());
        }

    运行结果:

    没错,我们设计的单链表没问题

    ①快慢指针:一个指针每次按着顺序跳两次,而另一个指针只跳一次,当第一个指针跳到的元素为空是,那么第二个指针就处于中间的位置

    /**
         * 获取中间元素
         * 
         * @return
         */
        public E getMiddle() {
            Node<E> n1 = first;// 每次只走一步,慢指针
            Node<E> n2 = first;// 每次走两步,快指针
            
            L: while (true) {
                if (n2.next != null && n2.next.next != null) {
                    n1 = n1.next;
                    n2 = n2.next.next;
                } else {
                    break L;
                }
            }
            return n1.item;
        }

    将上面的代码添加到MyLinkedList.java里面,测试

    public static void main(String[] args){
            MyLinkedList<Integer> list=new MyLinkedList<>();
            list.add(2);
            list.add(1);
            list.add(5);
            list.add(8);
            list.add(7);
            System.out.println(list.toString());
            System.out.println(list.getMiddle());
        }

    结果如下:

  • 相关阅读:
    数据库连接 执行 select 语句
    cygwin完全安装步骤方法(组图)
    Android 8位颜色值和6位颜色值的区别
    执行带参数的sql语句
    [Android环境搭建] 申请Android Map API Key
    调用存储过程
    [Android]应用语言切换的三种方法
    JS 的魅力
    Android工程 引用另外一个Android工程
    使用XML Security验证XML文件的数字签名
  • 原文地址:https://www.cnblogs.com/pig-brother/p/7347508.html
Copyright © 2011-2022 走看看