Java数据结构算法

目录node

 
  

 

 

链表

  “数组”做为数据存储结构有必定的缺陷数组

  • 无序数组——搜索效率是低效的
  • 有序数组——插入效率低

  无论在哪一种数组中删除效率都很低,建立数组后,大小不可改变数据结构

线性数据结构

  

     

为何链表很重要?

  • 最简单的动态数据结构
  • 更深刻的理解引用(或者指针)
  • 更深刻的理解递归
  • 辅助组成其余的数据结构(图结构、哈希表、队列)

链表 LinkedListapp

  数据储存在“节点(Node)”中,一个链节点是某个类的对象ide

  

  

  优势:真正的动态,不须要处理固定容量的问题(不用像数组new出来一片空间)this

  缺点:不能随机访问(数组开辟的空间在内存上是连续的,能够经过下标计算出内存地址进行随机访问,而链表必须是顺序访问,因为依靠next一层一层链接,在计算机的底层,每个节点对应的内存地址不一样spa

数组和链表的对比

  数组:最好用于索引有语意的状况(user[1])3d

  优势:快速查询指针

  数组:最好不用于索引有语意的状况code

  链表:动态


应用

一、在链表头添加元素

  在数组中,在最后面添加元素是最方便的,由于有size在跟踪数组的最后一个元素

  可是链表偏偏相反,链表头添加元素,由于有head头结点,没有跟踪最后一个元素的结点

  

public class LinkedList<E>{

    private class Node{
        public E e;
        public Node next;

        public Node(E e,Node next){
            this.e=e;
            this.next=next;
        }

        public Node(E e){
            this(e,null);
        }

        public Node(){
            this(null,null);
        }
    }

    private Node head;
    private int size;

    public LinkedList(){
        head=null;
        size=0;
    }

    //获取链表中元素个数

    public int getSize() {
        return size;
    }

    public boolean isEmpty(){
        return size==0;
    }

    //在链表头结点添加元素
    public  void addFirst(E e){
        Node node=new Node(e);
        node.next=head;
        head=node;

        //head=new Node(e);至关于上面三行
        size++;
    }
}
View Code

 

二、在链表中间(末尾)添加元素

   在搜索为2的位置插入元素

  

   关键:找到添加结点的前一个节点

  注意:如插入到索引为0的节点后面,头结点没有前驱节点

  //在链表中间添加元素
    public void add(int index,E e){
        //判断索引的和发现
        if(index<0||index>size){
            throw new IllegalArgumentException("add failed,illegal index");
        }
        //若是在链表头添加,因为链表头没有前驱节点,需特殊处理
        if(index==0){
            addFirst(e);
        }else{
            Node pre=head;
            for (int i = 0; i <index-1 ; i++) {
                //一直将前驱节点向前移,直到找到index位置的节点
                pre=pre.next;
                Node node=new Node(e);
                node.next=pre.next;
                pre.next=node;

                //pre.next=new Node(e,pre.next);至关于上面三行
                size++;
            }
        }
    }

    //在链表末尾添加元素
    public void addLast(E e){
        add(size,e);
    }
View Code

 三、为链表设置虚拟头结点

  因为头结点没有前驱节点,在链表头结点和其余位置插入元素,会有所不一样

  所以构建一个虚拟头结点为null,就不须要对头结点进行特殊处理,只须要找到待添加元素的前一个节点

  

    //在链表中间添加元素
    public void add(int index,E e){
        //判断索引的和发现
        if(index<0||index>size){
            throw new IllegalArgumentException("add failed,illegal index");
        }
        //若是在链表头添加,因为链表头没有前驱节点,需特殊处理
            Node pre=dummyHead;
            for (int i = 0; i <index; i++) {
                //一直将前驱节点向前移,直到找到index位置的节点
                pre=pre.next;
                Node node=new Node(e);
                node.next=pre.next;
                pre.next=node;

                //pre.next=new Node(e,pre.next);至关于上面三行
                size++;
            }
    }

    //在链表末尾添加元素
    public void addLast(E e){
        add(size,e);
    }

    //在链表头结点添加元素
    public void addFirst(E e){
        add(0,e);
    }
View Code

 四、链表

 

    //得到链表的第index(0-base)个位置的元素
    public E get(int index){
        //判断索引的合法性
        if(index<0||index>size){
            throw new IllegalArgumentException("add failed,illegal index");
        }
        Node cur=dummyHead.next;
        for (int i = 0; i <index ; i++) {
            cur=cur.next;
        }
        return cur.e;
    }

    //获取链表第一个元素
    public E getFirst(){
        return get(0);
    }

    public E getLast(){
        return get(size-1);
    }
View Code
相关文章
相关标签/搜索