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

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

 

liuyuhang原创,未经容许禁止转载java

 

目录node

算法是什么(〇)算法

 

不少语言的API中都提供了链表实现,或者扩展库中实现了链表。
数组

可是更多的状况下,Map(或hash)和List(非定容数组)的使用率更高。数据结构

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

 

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

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

 

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

因此,手写一个链表试试。

 

一、本质

 

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

和基础操做API构成

 

二、特性

 

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

 

三、基础API

 

链表的操做,至少须要增删改查,否则还算啥容器了:

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

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

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

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

 

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

  获取当前容器的size

  获取当前指针的index

  迭代器

  排序工具

  判空

  克隆

  转数组

  逆转

  去重复

  序列化

  等等。。。

 

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

 

四、Java中的链表

 

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

 

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

对于须要做为原子操做的各类功能的队列来讲,能够考虑。

 

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

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

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

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

  ④不受约束本身写一个吧。。。

 

五、写一个简单的链表

 

我尝试写了一个简单的链表,之前也大概看过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 + "]";
    }

}

 

测试可用,本身拿去玩吧。

 

以上!

相关文章
相关标签/搜索