Java数据结构-线性表之静态链表
静态链表的定义: 
节点由一个一维数组和一个指针域组成,数组用来存放数据元素,而指针域里面的指针(又称游标)用来指向下一个节点的数组下标。
这种链表称之为静态链表。
链表中的数组第一个和最后一个位置须要特殊处理,不存数据。第一个位置(即数组0下标)的节点的指针用来存放备用链表的第一个节点的数组下标。
最后一个位置(即数组长度MaxSize-1下标)的节点的指针用来存放指向有数值的第一个数据元素的数组下标,相似于单链表的头结点。
静态链表的演示样例图: 
 
 
以下举一个摘抄自《大话数据结构》的样例。来解释一下静态数据链表。 

以下介绍静态链表的插入和删除操作: 
这里我画了一张图,简单的描写叙述了一下。相信应该easy理解,例如以下: 
 
 
相同删除的演示样例图例如以下: 
 
 
以下贴一下我用Java实现的代码,主要功能仅仅实现了插入和删除操作:
package com.phn.datestructure;
/**
 * @author 潘海南
 * @Email 1016593477@qq.com
 * @TODO 静态链表
 * @date 2015年7月19日
 */
public class FOStaticList<E> {
    //静态链表的长度
    private int size;
    //静态链表的容量,实际容量为capacity-2:capacity-头结点-备用头结点=capacity-2
    private int capacity;
    //备用链表的头结点
    private FOStaticNode<E> backNode= null;
    //备用链表在数组中的位置。默觉得第一个,即为0
    private int backNodeIndex = 0;
    //静态链表的头结点,即静态链表数据元素链的头结点
    private FOStaticNode<E> headerNode = null;
    //静态链表的存储数据元素的数组
    private FOStaticNode<E>[] fosn = null;
    //默认容量
    private static final int DEFUALT_CAPACITY = 100;
    public FOStaticList(){
        this(DEFUALT_CAPACITY);
    }
    /**
     * @TODO 带參构造函数。用来初始化赋值静态链表,并进行相关容量和大小的设置
     * @param initialCapacity 静态链表的初始化容量
     */
    public FOStaticList(int initialCapacity) {
        this.init(initialCapacity);
        this.setCapacity(initialCapacity);
        this.setSize();
    }
    /**
     * @TODO 初始化赋值静态链表。并设置静态链表的头结点和备用链表的头结点
     * @param initialCapacity
     */
    private void init(int initialCapacity) {
        //推断给定的初始化參数是否合法
        if (initialCapacity < 0) {
            throw new RuntimeException("数组大小错误:" + initialCapacity);
        }
        fosn = new FOStaticNode[initialCapacity];
        //给静态链表赋值,内部的e=null。而游标设置为i+1
        for(int i = 0;i<initialCapacity-1;i++){
            fosn[i]  = new FOStaticNode<E>();
            fosn[i].setCursor(i+1);
        }
        fosn[initialCapacity-1] = new FOStaticNode<E>();
        //设置静态链表的头结点指向备用链表的数组下标,即initialCapacity-1的节点的游标为0
        fosn[initialCapacity-1].setCursor(backNodeIndex);
        //设置静态链表的头结点为headerNode
        this.setHeaderNode(fosn[initialCapacity-1]);
        //设置备用链表的头结点为backNode
        this.setBackNode(fosn[backNodeIndex]);
    }
    /**
     * @TODO 静态链表尾插法加入数据元素
     * @param e 要加入的数据元素
     * @return true
     */
    public boolean add(E e){
        //检查链表的容量,并进行对应的扩容
        this.ensureCapacity(size);
        //将备用链表头结点指向的游标(即备用链表的第一个位置)赋值给oldBackNodeCursor保存
        int oldBackNodeCursor = this.backNode.getCursor();
        if(size==0){
            /*若眼下(即加入元素之前)静态链表没有数据元素,则将静态链表的头结点的游标指向
         *   “备用链表头结点指向的游标对应的位置”,即备用链表的第一个元素位置*/
            this.headerNode.setCursor(oldBackNodeCursor);
        }else{
            //将静态链表的头结点指向的游标赋值给tempNodeCursor
            int tempNodeCursor = this.headerNode.getCursor();
            //以下的循环用来找到静态链表(数据元素链)的最后一个元素节点lastNode
            FOStaticNode<E> lastNode = new FOStaticNode<E>();
            while(tempNodeCursor!=0){
                lastNode= this.fosn[tempNodeCursor];
                tempNodeCursor= this.fosn[tempNodeCursor].getCursor();
            }
            //将lastNode节点的指向游标设置值为备用链表的第一个位置
            lastNode.setCursor(oldBackNodeCursor);
        }
        //将备用链表的第一个位置设置数据元素为e
        this.fosn[oldBackNodeCursor].setE(e);
        //获取备用链表的第一个位置指向的游标,并将其赋值给newBackNodeCursor(作为新的备用链表头结点指向的游标)保存,
        int newBackNodeCursor = this.fosn[oldBackNodeCursor].getCursor();
        //设置备用链表的第一个位置(即眼下作为静态链表数据元素链的最后一个元素)指向的游标为备用链表的头结点位置(默认0位置)
        this.fosn[oldBackNodeCursor].setCursor(backNodeIndex);
        //设置备用链表头结点指向的游标为新的备用链表头结点指向的游标newBackNodeCursor
        this.backNode.setCursor(newBackNodeCursor);
        //链表长度加1
        this.size++;
        return true;
    }
    /**
     * @TODO 依据提供的index来删除静态链表中的第index个元素
     * @param index 静态链表中的第index个元素
     * @return true or false
     */
    public boolean remove(int index){
        //推断给出的元素位置是否合法;this.capacity-2表示静态链表可以达到的最大长度:capacity-头结点-备用头结点=capacity-2
        if(index<1 || index>this.capacity-2){
            System.out.println("不存在此位置的元素");
            return false;
        }
        //声明变量preRemoveCursor用来作为将要删除的数据元素数组的下标。或者称为将要删除的数据元素的前一个节点指向的游标。
        int preRemoveCursor = this.headerNode.getCursor();
        //以下的循环用来找出删除的数据元素的前一个节点preRemoveNode和将要删除的数据元素的前一个节点指向的游标preRemoveCursor
        FOStaticNode<E> preRemoveNode = new FOStaticNode<E>();
        int tempCount = 0;
        while(tempCount!=index-1){
            preRemoveNode = this.fosn[preRemoveCursor];
            preRemoveCursor = preRemoveNode.getCursor();
            tempCount++;
        }
        //声明变量oldBackNodeCursor作为备用链表的头结指向的游标并赋值保存。
int oldBackNodeCursor = this.backNode.getCursor();
        //设置备用链表的头结点指向的游标为 将要删除的数据元素数组的下标 preRemoveCursor
        this.backNode.setCursor(preRemoveCursor);
        //将将要删除的数据元素指向的游标赋值给removeCursor并保存
        int removeCursor = this.fosn[preRemoveCursor].getCursor();
        //将将要删除的数据元素指向的游标设置为备用链表的头结指向的游标oldBackNodeCursor
        this.fosn[preRemoveCursor].setCursor(oldBackNodeCursor);
        //将将要删除的数据元素设置为null,即删除
        this.fosn[preRemoveCursor].setE(null);
        //将将要删除的数据元素的前一个节点指向的游标设置为将要删除的数据元素指向的游标removeCursor
        preRemoveNode.setCursor(removeCursor);
        //长度减1
        this.size--;
        return true;
    }
    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer("[ ");
        int currentCursor = this.headerNode.getCursor();
        if(currentCursor!=backNodeIndex){
            sb.append(currentCursor+""+this.fosn[currentCursor]);
            currentCursor = this.fosn[currentCursor].getCursor();
            while(currentCursor!=backNodeIndex){
                sb.append(", "+currentCursor+""+this.fosn[currentCursor]);
                currentCursor = this.fosn[currentCursor].getCursor();
            }
        }
        return sb.append(" ]").toString();
    }
    /**
     * @TODO 推断静态链表的容量是否超过,并进行对应的扩容操作。
* 注意:这里最基本的是将当前静态链表数组下标最后一个位置的游标保存起来。即将头结点指向的游标保存起来;
     * 然后赋值给新的静态链表的头结点指向的游标。
     * @param currentSize 当前长度
     */
    private void ensureCapacity(int currentSize) {
        if(currentSize == this.capacity-2){
            int oldCapacity = this.capacity;
            //这里我是依照ArrayList的扩容来进行的,扩大约1.5倍左右。
            this.capacity = (this.capacity * 3) / 2 + 1;
            FOStaticNode<E>[] newData = new FOStaticNode[this.capacity];
            for (int i = 0; i < oldCapacity-1; i++) {
                newData[i] = this.fosn[i];
            }
            newData[capacity-1]  = new FOStaticNode<E>();
            newData[capacity-1].setCursor(this.fosn[oldCapacity-1].getCursor());
            for(int i = oldCapacity-1;i<this.capacity-1;i++){
                newData[i]  = new FOStaticNode<E>();
                newData[i].setCursor(i+1);
            }
            this.fosn = newData;
        }
    }
    /**
     * @return the size
     */
    public int size() {
        return size;
    }
    private void setSize() {
        this.size=0;
    }
    /**
     * @param backNode the backNode to set
     */
    private void setBackNode(FOStaticNode<E> backNode) {
        this.backNode = backNode;
    }
    /**
     * @param headerNode the headerNode to set
     */
    private void setHeaderNode(FOStaticNode<E> headerNode) {
        this.headerNode = headerNode;
    }
    /**
     * @param capacity the capacity to set
     */
    private void setCapacity(int capacity) {
        this.capacity = capacity;
    }
}
在举一个删除的演示样例图,请联系我的代码进行操作, 
首先写个測试的方法
public static void main(String[] args) {
    FOStaticList<String> fosl = new FOStaticList<String>(6);
    fosl.add("元素1");
    System.out.println(fosl);
    fosl.add("元素2");
    fosl.add("元素3");
    System.out.println(fosl);
    fosl.add("元素4");
    System.out.println(fosl);
    System.out.println(fosl.size());
    fosl.remove(2);
    System.out.println(fosl);
}
执行測试方法,结合下图应该可以比較好的理解。

最后说说静态链表的优缺点。 

Java数据结构-线性表之静态链表的更多相关文章
- Java数据结构-线性表之单链表LinkedList
		线性表的链式存储结构,也称之为链式表,链表:链表的存储单元能够连续也能够不连续. 链表中的节点包括数据域和指针域.数据域为存储数据元素信息的域,指针域为存储直接后继位置(一般称为指针)的域. 注意一个 ... 
- [数据结构-线性表1.2] 链表与 LinkedList<T>(.NET 源码学习)
		[数据结构-线性表1.2] 链表与 LinkedList<T> [注:本篇文章源码内容较少,分析度较浅,请酌情选择阅读] 关键词:链表(数据结构) C#中的链表(源码) 可空类 ... 
- 【Java】 大话数据结构(3) 线性表之静态链表
		本文根据<大话数据结构>一书,实现了Java版的静态链表. 用数组描述的链表,称为静态链表. 数组元素由两个数据域data和cur组成:data存放数据元素:cur相当于单链表中的next ... 
- Java数据结构-线性表之顺序表ArrayList
		线性表的顺序存储结构.也称为顺序表.指用一段连续的存储单元依次存储线性表中的数据元素. 依据顺序表的特性,我们用数组来实现顺序表,以下是我通过数组实现的Java版本号的顺序表. package com ... 
- c数据结构链式存储-静态链表
		#include "string.h" #include "ctype.h" #include "stdio.h" #include &qu ... 
- javascript实现数据结构与算法系列:线性表的静态单链表存储结构
		有时可借用一维数组来描述线性链表,这就是线性表的静态单链表存储结构. 在静态链表中,数组的一个分量表示一个结点,同时用游标(cur)代替指针指示结点在数组中的相对位置.数组的第0分量可看成头结点,其指 ... 
- [数据结构 - 第3章] 线性表之单链表(C++实现)
		一.类定义 单链表类的定义如下: #ifndef SIGNALLIST_H #define SIGNALLIST_H typedef int ElemType; /* "ElemType类型 ... 
- [从今天开始修炼数据结构]线性表及其实现以及实现有Itertor的ArrayList和LinkedList
		一.线性表 1,什么是线性表 线性表就是零个或多个数据元素的有限序列.线性表中的每个元素只能有零个或一个前驱元素,零个或一个后继元素.在较复杂的线性表中,一个数据元素可以由若干个数据项组成.比如牵手排 ... 
- 玩转C线性表和单向链表之Linux双向链表优化
		前言: 这次介绍基本数据结构的线性表和链表,并用C语言进行编写:建议最开始学数据结构时,用C语言:像栈和队列都可以用这两种数据结构来实现. 一.线性表基本介绍 1 概念: 线性表也就是关系户中最简单的 ... 
随机推荐
- [oldboy-django][4python面试]面试前需要熟练掌握的知识点(待更新)
			python基础 - 生成器 - 装饰器 - 迭代器 - 列表生成式 - 引用,传参 - 面向对象,继承 前端Html: - 词法分析 - 作用域 - 语法分析 - this - Jsonp mysq ... 
- 【bzoj1336/1337/2823】[Balkan2002]Alien最小圆覆盖  随机增量法
			题目描述 给出N个点,让你画一个最小的包含所有点的圆. 输入 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000. ... 
- 【bzoj4127】Abs  树链剖分+线段树
			题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ... 
- 实例对比 Julia, R, Python,谁是狼语言?
			对于一个平台来说,使用者对技术本身是不敏感的,所以我们需要增加一些限制来减少集群的一些不可控情况,例如不断的写入新表/新数据却不记得删除,大量不按规范创建的表名等情况.与此同时应尽量让技术对用户透明, ... 
- [luoguP2657] [SCOI2009]windy数(数位DP)
			传送门 f[i][j]表示位数为i,第i位为j的windy数的个数 先预处理出f数组. 求的时候先算没有前导0的答案,再算位数和给定的数相同的答案. #include <cmath> #i ... 
- 数位DP毕业题
			原题 题意 给一个 $64$ 位的二进制数,求小于这个数的回文二进制数的数量. 题解 加强版 题意 同上,但允许一个数最多有 $k$ 位不是回文(即把任意 $k$ 位取反后这个数是一个回文数),这种数 ... 
- dockerfile  镜像构建
			1.镜像的构建有手动与自动方式,这里我们介绍自动化的构建方式 ,dockerfile常用指令如下 2.构建指令build Usage: docker image build [OPTIONS] PAT ... 
- Python 安装MySQLdb模块遇到报错及解决方案:_mysql.c(42) : fatal error C1083: Cannot open include file: 'config-win.h': No such file or directory
			一.问题 系统:win7 64位 在下载MySQL-python-1.2.5.zip,使用python setup.py install 安装时,出现以下报错: _mysql.c(42) : fata ... 
- 一个html5视频播放器
			具有播放视频,拖拽,自定义右键菜单,上传头像的功能 <!DOCTYPE html><html lang="en"> <head> <met ... 
- JavaScript 笔记(1) -- 基础 & 函数 & 循环 & ...
			目录(代码编写): 显示数据 语法 变量 & 变量类型 对象 函数 事件 字符串 运算符 条件语句 循环语句 Break 和 Continue 使用 JS 近两年,现整理下一些基本: HTML ... 
