.线性表链式存储结构:将采用一组地址的任意的存储单元存放线性表中的数据元素。
链表又可分为:

  • 单链表:每个节点只保留一个引用,该引用指向当前节点的下一个节点,没有引用指向头结点,尾节点的next引用为null。

  • 循环链表:一种首尾相连的链表。

  • 双向链表:每个节点有两个引用,一个指向当前节点的上一个节点,另外一个指向当前节点的下一个节点。

下面给出线性表双向链表的实现:java中LinkedList是线性表的链式实现,是一个双向链表。

import java.util.NoSuchElementException;

//线性表双向链表存储结构
public class DuLinkList<T> {

//定义一个内部类Node,Node实例代表链表的节点
    private class Node{
        //保存节点的数据
        private T data;
        //指向上一个节点的引用
        private Node prev;
        //指向下一个节点的引用
        private Node next;
        //无参数的构造器
        public Node(){
            
        }
        //初始化全部属性的构造器
        public Node(T data, Node prev, Node next){
            this.data = data;
            this.prev = prev;
            this.next = next;
        }        
    }
    //保存该链表的头结点
    private Node header;
    //保存该链表的尾节点
    private Node tail;
    //保存该链表中已包含的节点数
    private int size;
    //创建空链表
    public DuLinkList(){
        //空链表,header与tail都是null
        header = null;
        tail = null;
    }
    //以指定数据元素来创建链表,该链表只有一个元素
    public DuLinkList(T element){
        header = new Node(element, null, null);
        tail = header;
        size++;
    }
    //判断链式线性表是否为空链表
    public boolean empty(){
        return size == 0;
    }
    //清空线性表
    public void clear(){
        for(Node current = header; current != null;){
            Node next = header.next;
            current.data = null;
            current.prev = null;
            current.next = null;
            current = next;
        }
        header = null;
        tail = null;
        size = 0;
    }
    //获取链式线性表中索引为index处的元素
    public T get(int index){
        return getNodeByIndex(index).data;
    }
    //根据索引index获取指定位置的节点
    private Node getNodeByIndex(int index){
        if(index < 0 || index > size -1){
            throw new IndexOutOfBoundsException("线性表索引越界");
        }
        if(index < (size >> 1)){
            //从header节点开始遍历
            Node current = header;
            for(int i=0; i < index; i++){
                current = current.next;
            }
            return current;
        }else{
            Node current = tail;
            for(int i = size - 1; i > index; i--){
                current = current.prev;
            }
            return current;
        }
    }
    //查找链式线性表中指定元素的索引
    public int locate(T element){
        Node current = header;
        for(int i=0;i<size && current != null;i++, current = current.next){
            if(current.data.equals(element)){
                return i;
            }
        }
        return -1;
    }
    //返回链表的长度
    public int length(){
        return size;
    }
    //向线性链表的表头插入一个元素
    public void addFirst(T element){
        linkFirst(element);
    }
    //在线性链表表头插入一个元素
    public void linkFirst(T element){
        Node f = header;
        Node newNode = new Node(element,null,f);
        header = newNode;
        if(f == null){
            tail = newNode;
        }else{
            f.prev = newNode;
        }
        size++;
    }
    //向线性链表的表尾插入一个元素
    public void addTail(T element){
        linkTail(element);
    }
    //在线性链表的表尾插入一个元素
    public void linkTail(T element){
        Node t = tail;
        Node newNode = new Node(element, t, null);
        tail = newNode;
        if(t == null){
            header = newNode;
        }else{
            t.next = newNode;
        }
        size++;
    }
    //在线性表中某个元素前面插入一个节点
    public void linkBefore(T element, Node node){
        Node pre = node.prev;
        Node newNode = new Node(element, pre, node);
        node.prev = newNode;
        if(pre == null){
            header = newNode;
        }else{
            pre.next = newNode;
        }
        size++;
    }
    //向线性链表中的指定位置插入一个元素
    public void insert(T element, int index){
        if(index < 0 || index > size){
            throw new IndexOutOfBoundsException("线性表索引越界");
        }
        if(index == size){
            addTail(element);
        }else{
            linkBefore(element,getNodeByIndex(index));
        }
    }
    //移走线性链表的头结点
    public void removeFirst(){
        Node first = header;
        if(first == null)
            throw new NoSuchElementException("此节点不存在");
        unlinkFirst(first);
    }
    //删除头结点
    public void unlinkFirst(Node node){
        Node next = node.next;    
        node.data = null;
        node.next = null;
        header = next;
        if(next == null){
            tail = null;
        }else{
            next.prev = null;
        }
        size--;
    }
    //移走线性链表的尾节点
    public void removeTail(){
        Node last = tail;
        if(last == null)
            throw new NoSuchElementException("此节点不存在");
        unlinkLast(last);
    }
    //删除尾节点
    public void unlinkLast(Node node){
        Node pre = node.prev;
        node.data = null;
        node.prev = null;
        tail = pre;
        if(pre == null){
            header = null;
        }else{
            pre.next = null;
        }
        size--;
    }
    //移走线性表中的任意一个节点
    public void remove(int index){
        if(index < 0 || index >size - 1){
            throw new IndexOutOfBoundsException("线性表越界");
        }
        unlink(getNodeByIndex(index));
    }
    //删除线性表中任意一个元素
    public void unlink(Node node){
        Node pre = node.prev;
        Node next = node.next;
        node.data = null;
        if(pre == null){
            header = next;
        }else{
            pre.next = next;
            node.prev = null;
        }
        if(next == null){
            tail = pre;
        }else{
            next.prev = pre;
            node.next = null;
        }
        size--;
    }
}

线性链表的双向链表——java实现的更多相关文章

  1. 【Java】 大话数据结构(5) 线性表之双向链表

    本文根据<大话数据结构>一书,实现了Java版的双向链表. 在每个数据结点中都有两个指针,分别指向直接后继和直接前驱,这样的链表称为双向链表. 双向链表的结构如图所示: 查找元素可以根据元 ...

  2. javascript实现数据结构:线性表--线性链表(链式存储结构)

    上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...

  3. 【二叉树->链表】二叉树结构转双向线性链表结构(先序遍历)

    二叉树存储结构属于非线性链表结构,转化成线性链表结构,能简化操作和理解.然而由非线性转线性需要对整个树遍历一次,不同的遍历方式转化结果页不一样.下面以先序为例. 方法一: 递归法.递归遍历二叉树,因为 ...

  4. c/c++ 线性表之双向链表

    c/c++ 线性表之双向链表 线性表之双向链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,每个节点的before都指向前一个节点,最后一个节点的下一个节点是NULL. 真实 ...

  5. [C++]线性链表之顺序表<二>

    /*   @content 线性链表之顺序表   @date 2017-3-21 1:06   @author Johnny Zen  */ /* 线性表     顺序表     链式表[带头指针/不 ...

  6. 【 C# 】(一) ------------- 泛型带头节点的单链表,双向链表实现

    在编程领域,数据结构与算法向来都是提升编程能力的重点.而一般常见的数据结构是链表,栈,队列,树等.事实上C#也已经封装好了这些数据结构,在头文件 System.Collections.Generic ...

  7. 线性表结构的Java实现

    一.线性表的抽象数据类型表述 线性表的结构简单,长度允许动态增长或搜索:可以对线性表中的任何数据元素进行访问和查找:允许进行数据的插入和删除操作:求线性表中的指定数据的前驱和后继:合并线性表以及拆分线 ...

  8. [数据结构 - 第3章] 线性表之双向链表(C语言实现)

    一.什么是双向链表? 双向链表(double linked list)是在单链表的每个结点中,再设置一个指向其前驱结点的指针域.所以在双向链表中的结点都有两个指针域,一个指向直接后继,另一个指向直接前 ...

  9. 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作

    一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...

随机推荐

  1. MYSQL查询计划KEY_LEN

    http://www.innomysql.com/article/25241.html 1 key_len的含义 2 MySQL中key_len计算规则 3 通过key_len分析联合索引 本文首先介 ...

  2. QSplashScreen类实现Qt程序启动画面

      QSplashScreen类实现Qt程序启动画面 收藏人:zwsj     2013-09-13 | 阅:569  转:6    |   来源   |  分享               程序启动 ...

  3. Five ways to maximize Java NIO and NIO.2--reference

    Java NIO -- the New Input/Output API package-- was introduced with J2SE 1.4 in 2002. Java NIO's purp ...

  4. css 权威指南笔记(二)元素

    替换元素 用来替换元素内容的部分并非有文档内容直接表示. img input 非替换元素 其内容由用户代理(通常是一个浏览器)在元素本身生成的框中显示. 块级元素 块级元素生成一个 元素框,(默认)会 ...

  5. sqlserver 2008表分区操作

    表分区操作步骤 1.设计表进行分区的方案,水平分区.垂直分区 a.水平切割将减少表的行数,这样可以将历史数据归档,减少表大小,提高访问速度. b.垂直切割将分为主表和从表方式,将主要的列字段存放在主表 ...

  6. Java-分页实例

    1.PageModel.java package com.javaweb; import java.util.List; public class PageModel<E> { priva ...

  7. Java-Android 之电话拨号源码

    file:///F:/workspace3/Android_ver2.4/src/cn/szy/com/MainActivity.java package cn.szy.com; import and ...

  8. 开源的Android开发框架-------PowerFramework使用心得(五)网络请求HTTPRequest

    GET请求示例 //所有参数都使用Bundle,用putString Bundle bundle = new Bundle(); bundle.putString("username&quo ...

  9. startActivityForResult和setResult详解

    http://www.cnblogs.com/lijunamneg/archive/2013/02/05/2892616.html startActivityForResult与startActivi ...

  10. ASP 调用dll(VB)及封装dll实例

    ASP调用dll及封装dll实例,封装为dll可以提供运行效率,加密代码. 打开VB6,新建ActiveX DLL 2.在工程引用中加入Microsoft Active Server Pages Ob ...