线性表--双链表实现方式 (JAVA)

          欢迎讨论,转载请注明出处哦

               前面一篇文章说明了线性表主要有三种结构:顺序表、单链表、双链表。

         其实按照其实现的特点是两种实现方式:1、采用数组式的静态存储空间,即线性表;2、采用链

         式的动态 存储空间,即是链表。

              上一章实现了顺序表,这篇文章用于实现双链表。由于双链表具有的方法比顺序表多。

         因此重新定义一个线性表接口:

package com.kiritor.linklist;

/**
 * 线性表接口
 * @author Kiritor
 * */
public interface LinearTable<T>{
  //判空
  public boolean isEmpty();
  //获取长度
  public int getLength();
  //返回某个位置的元素
  public  T getData(int index);
  //设置index位置的元素,并返回先前的元素
  public  T setData(int index,T element);
  //插入一个元素,位置没有限定(插入链表尾部)
  public  boolean addData(T element);
  //在指定的位置插入一个元素
  public  boolean addData(int index,T element);
  //删除某个位置的元素,并返回该元素
  public  T removeData(int index);
  //清空线性表
  public boolean clearData(); 
  //删除尾部
  public boolean removeTail();
  
}
                  接下来就是实现了

package com.kiritor.linklist;

/**
 * java版双向链表的实现
 * 
 * @author Kiritor
 */
public class DBLinkList<T> implements LinearTable<T> {

    // 指向链表的头结点
    private Node head;
    // 指向链表的尾结点
    private Node tail;
    private int size = 0;// 链表的元素个数


    public DBLinkList() {
        this.head = new Node();
        this.tail = null;
    }

    public DBLinkList(T data) {
        this.head = new Node(null, data, null);
        this.tail = this.head;
        this.size++;
    }

    @Override
    public boolean isEmpty() {
        // TODO Auto-generated method stub
        return this.size == 0;
    }

    // 获得链表的长度
    public int getLength() {
        return this.size;
    }

    // 获取指定位置结点,下表从0开始
    public Node getNode(int index) {
        if (index < 0 || index > this.size - 1)
            throw new IndexOutOfBoundsException("访问位置非法越界!");
        // 根据index所出的位置决定是从前遍历还是从后遍历
        if (index <= this.size / 2) {// 位置在前半部分,则从头开始搜索
            Node curent = this.head;
            for (int i = 0; i <= this.size / 2 && curent != null; i++, curent = curent.next)
                if (i == index)
                    return curent;
        } else {// 位置在后半部分,则从后开始往前搜索
            Node curent = this.tail;
            for (int i = this.size - 1; i > this.size / 2 && curent != null; i--, curent = curent.pre)
                if (i == index)
                    return curent;
        }
        return null;
    }

    // 获取指定位置的结点元素
    public T getData(int index) {
        return this.getNode(index).data;
    }

    @Override
    public T setData(int index, T element) {
        return null;
    }

    // 在链表的头部插入元素,不指定位置默认在头部插入
    @Override
    public boolean addData(T element) {
        // 前驱引用为null,后继引用为头结点
        Node node = new Node(null, element, this.head);
        this.head.pre = node;// 改变前驱引用
        // 修改链表的头结点
        this.head = node;
        if (tail == null)
            tail = this.head;
        this.size++;
        // System.out.println(head.data+""+this.size);
        return true;
    }

    // 尾部插入
    public boolean addTail(T data) {
        if (this.head == null) {
            this.head = new Node(null, data, null);
            this.tail = this.head;
        } else {
            Node newnode = new Node(this.tail, data, null);
            this.tail.next = newnode;
            this.tail = newnode;
        }
        this.size++;
        // System.out.println(tail.data+""+this.size);
        return true;
    }

    //下表从0开始
    @Override
    public boolean addData(int index, T element) {
        if (index < 0 || index > this.size)
            throw new IndexOutOfBoundsException("不能在该位置插入元素,索引越界");
        if (this.head == null)
            this.addTail(element);// 尾部插入
        else {
            if (index == 0)
                this.addData(element);// 头部插入
            else {
                Node prev = this.getNode(index - 1);// 找到index-1处的节点
                Node next = prev.next;
                Node newnode = new Node(prev, element, next);// 分配节点
                prev.next = newnode;
                next.pre = newnode;
                this.size++;
            }
        }
        return true;
    }

    public String toString() {
        if (this.isEmpty())
            return "[]";
        else {
            StringBuffer st = new StringBuffer("[");
            for (Node curent = this.head; curent != null; curent = curent.next)
                st.append(curent.data.toString() + " ,");
            st.append("]");
            return st.toString();
        }
    }

    // 反向遍历链表
    public String reversetoString() {
        if (this.isEmpty())
            return "[]";
        else {
            StringBuffer st = new StringBuffer("[");
            for (Node curent = this.tail; curent != null; curent = curent.pre)
                st.append(curent.data.toString() + " ,");
            st.append("]");
            return st.toString();
        }
    }
    /**删除指定位置的结点,下表从0开始*/
    @Override
    public T removeData(int index) {
        if (index < 0 || index > this.size - 1)
            throw new IndexOutOfBoundsException("不能删除该位置的元素,索引越界");
        Node del = null;
        if (index == 0) {// 删除的为头节点
            del = this.head;
            this.head = this.head.next;
            this.head.pre = null;
            size--;
        }
        else if(index==size-1)
        {
            Node prev = this.getNode(index - 1);//找到删除位置的前驱
            del = prev.next;//找到要删除的结点
            prev.next = del.next;
            if (del.next != null)
                del.next.pre = prev;
            del.pre = null;
            del.next = null;
            
            size--;
            this.tail.next = null;
            this.tail.pre=prev;
            this.tail = prev;
        }
        else {
            Node prev = this.getNode(index - 1);//找到删除位置的前驱
            del = prev.next;//找到要删除的结点
            prev.next = del.next;
            if (del.next != null)
                del.next.pre = prev;
            del.pre = null;
            del.next = null;
            
            size--;
            
        }
        return null;
    }
    @Override
    public boolean removeTail() {
        removeData(this.size-1 );
        return false;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    @Override
    public boolean clearData() {
        this.head = null;
        this.tail = null;
        this.size = 0;
        return true;
    }

    /** 链表的节点类型 */
    class Node {
        public T data;
        public Node pre;// 便于访问的需要,设置为public
        public Node next;

        public Node() {
        };

        public Node(Node pre, T data, Node next) {
            this.data = data;
            this.pre = pre;
            this.next = next;
        }
    }

    

}

             简单的看看输出结果:

                       

              对于其具体分析就一个removeData(int index)方法为例吧(index>=1&&index<=size-1)

              

      

             

    

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值