zoukankan      html  css  js  c++  java
  • 算法是什么(二)手写个链表(java)

    算法是什么(二)手写个链表(java)

     

    liuyuhang原创,未经允许禁止转载

    目录

    算法是什么(〇)

    很多语言的API中都提供了链表实现,或者扩展库中实现了链表。

    但是更多的情况下,Map(或hash)和List(非定容数组)的使用率更高。

    这并非意味着链表不应该掌握或不使用了。

    链表本质上是一种及其高等的数据结构展现,扩展性极强。

    链表可轻松扩展成树结构,二叉树,环,栈,队列,双向队列等。

    很多种数据结构都是依据链表的形式扩展出来的,虽然我知道的并不多,但是我知道链表的重要性。

    所以,手写一个链表试试。

    1、本质

    链表的本质是Node(节点),其中保存着信息(info),前一个节点(prevNode),后一个节点(nextNode)。

    和基础操作API构成

     

    2、特性

    链表为了操作的方便性,多数会将链表做成双向链表,即既包含next,又包含prev

    3、基础API

    链表的操作,至少需要增删改查,不然还算啥容器了:

      增:默认从末尾添加,添加指定index,在首添加三种方式添加单一元素。

      删:删除头,删除尾,删除指定index的元素,删除当前指针元素。

      改:设置头,设置尾,设置指定index的元素,设置当前指针元素。

      查:获取当前指针元素,获取首元素,获取尾元素,获取下一个元素,获取上一个元素,获取指定index的元素

      有些API还提供了更多的操作:

      获取当前容器的size

      获取当前指针的index

      迭代器

      排序工具

      判空

      克隆

      转数组

      逆转

      去重复

      序列化

      等等。。。

    链表可做的操作会比想象的多的多。

    4、Java中的链表

     

    Java中常用的链表是LinkedList,实现了List接口,继承AbstractLinkedList。同时还有其他接口

    同时,还有Queue大类,并非在Collection接口下,但是底层有些是使用链表实现的,功能有些是重复的。

    对于需要作为原子操作的各种功能的队列来说,可以考虑。

    在扩展Java中的链表的时候,有几种方式供选择:

      ①继承LinkedList,添加扩展算法;

      ②实现List,继承AbstractLinkedList,同时扩展算法;

      ③使用装饰模式,在构造器中调用链表的构造器,同时扩展算法;

      ④不受约束自己写一个吧。。。

    5、写一个简单的链表

    我尝试写了一个简单的链表,以前也大概看过C的链表和Java的链表,写的过程中全凭记忆,

    大约花了十个小时才写完,哩哩啦啦好多天。

    代码拙劣,为了以后尝试链表的其他算法(排序,转换,反转,环链表,扩展二叉树)做准备。

    代码如下:

    package com.FM.ArrayStudy;
    
    public class SimpleLinkedList<T> {
    
        private Node<T> pointer;// 当前指针节点
        private Node<T> firstNode;// 首个节点
        private Node<T> lastNode;// 末尾节点
        private Integer index = 0;// 当前指针index
        private Integer size = 0;// 当前容量
    
        /**
         * 获取当前pointer的info
         * @return
         */
        public T getThis() {
            if (null == pointer) {
                return firstNode.info;
            } else {
                return pointer.info;
            }
        }
    
        /**
         * 获取下一个元素的内容,若没有下一个元素,则返回null
         * 
         * @return
         */
        public T getNext() {
            if (index.equals(size - 1)) {
                return null;
            } else {
                if (null == pointer) {
                    pointer = firstNode;
                    pointer = pointer.next;
                    T info = pointer.info;
                    index++;
                    return info;
                } else {
                    pointer = pointer.next;
                    T info = pointer.info;
                    index++;
                    return info;
                }
            }
        }
    
        /**
         * 修改指定index的元素的方法
         * 
         * @param index
         * @param t
         * @throws Exception
         */
        public void set(Integer index, T t) throws Exception {
            if (index > -1 && index < size - 1) {
                Node<T> node = getNodeByIndex(index);
                node.info = t;
            } else {
                throw new Exception("get ele " + index + " out of index");
            }
        }
    
        /**
         * 修改首元素
         * 
         * @param t
         */
        public void setFirst(T t) {
            firstNode.info = t;
        }
    
        /**
         * 修改尾元素
         * 
         * @param t
         */
        public void setLast(T t) {
            lastNode.info = t;
        }
    
        /**
         * 从指定index移除node的方法
         * 
         * @param index
         * @throws Exception
         */
        public void remove(Integer index) throws Exception {
            if (index > -1 && index < size) {
                if (index.equals(0)) {
                    Node<T> node = getNodeByIndex(1);
                    firstNode = node;
                    firstNode.prve = null;
                } else if (index.equals(size - 1)) {
                    Node<T> node = getNodeByIndex(size - 2);
                    lastNode = node;
                    lastNode.next = null;
                } else {
                    Node<T> node = getNodeByIndex(index);
                    Node<T> nextNode = node.next;
                    Node<T> prveNode = node.prve;
                    prveNode.next = nextNode;
                    nextNode.prve = prveNode;
                    node = null;
                }
                size--;
            } else {
                throw new Exception("get ele " + index + " out of index");
            }
    
        }
    
        /**
         * 获取当前元素在链表中的位置
         * 
         * @return
         */
        public int getIndex() {
            return index;
        }
    
        /**
         * 获取当前链表size的方法
         * 
         * @return
         */
        public Integer size() {
            return size;
        }
    
        /**
         * 判断容器是否为空的方法,为空返回true
         * 
         * @return
         */
        public boolean isEmpty() {
            if (size.equals(0)) {
                return true;
            } else {
                return false;
            }
    
        }
    
        /**
         * 根据index查询链表中元素的方法
         * 
         * @param index
         * @return
         * @throws Exception
         */
        public T getByIndex(Integer index) throws Exception {
            if (index > -1 && index < size) {
                Node<T> nodeByIndex = getNodeByIndex(index);
                return nodeByIndex.info;
            } else {
                throw new Exception("get ele " + index + " out of index");
            }
        }
    
        /**
         * 根据index获取node的方法
         * 
         * @param index
         * @return
         */
        private Node<T> getNodeByIndex(Integer index) {
            Node<T> temp = firstNode;// 取firstnode
            if (index != 0) {// 查看当前index,若index!=0,则递归直到index
                for (int i = 0; i < index; i++) {
                    temp = temp.next;
                }
            }
            this.index = index;// 调整当前index
            return temp;// 返回节点
        }
    
        /**
         * 向链表末尾默认添加一个元素的方法
         * 
         * @param t
         */
        public void add(T t) {
            if (size == 0) {// 首次创建
                Node<T> node = new Node<T>();
                firstNode = node;
                lastNode = node;
                node.info = t;
                size++;
            } else {
                lastNode.next = new Node<T>();
                lastNode.next.info = t;
                lastNode.next.prve = lastNode;
                lastNode = lastNode.next;
                size++;
            }
        }
    
        /**
         * 在首添加元素
         * 
         * @param t
         */
        public void addFirst(T t) {
            if (size == 0) {
                add(t);
            } else {
                Node<T> node = new Node<T>();
                node.info = t;
                node.next = firstNode;
                node.prve = null;
                firstNode.next = node;
                size++;
            }
        }
    
        /**
         * 在尾部添加元素
         * 
         * @param t
         */
        public void addLast(T t) {
            add(t);
        }
    
        /**
         * Node节点 链表内部数据结构和指针
         * 
         * @author Liuyuhang
         * @param <T>
         */
        private class Node<T> {
            T info;// 储存info
            Node<T> next;// 下一个节点指针
            Node<T> prve;// 上一个节点指针
    
            @Override
            public String toString() {// 同时打印next和prev会导致无限引用,堆栈溢出
                return "Node [info=" + info + ", next=" + next + "]";
            }
    
        }
    
        @Override
        public String toString() {// 打印first节点会因为next引出整个链表的所有内容
            return "SimpleLinkedList [node=" + firstNode + "]";
        }
    
    }

    测试可用,自己拿去玩吧。

    以上!

  • 相关阅读:
    五大主流浏览器 CSS3 和 HTML5 兼容性大比拼
    httpservice 公共类
    Eclipse自动生成注释
    天生一对"Maven2+Jetty" Maven2创建并管理WebApp,并使用Maven Jetty Plugin在Eclipse中调试
    jsp checkbox不错的应用
    我们需要改变
    Sortable Table 可排序表格JS收集
    Eclipse快捷键大全()
    Ajax简单应用
    css 固定table表头
  • 原文地址:https://www.cnblogs.com/liuyuhangCastle/p/9853447.html
Copyright © 2011-2022 走看看