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 概念: 线性表也就是关系户中最简单的 ...
随机推荐
- centos 7 配置ip
1.动态获取ip(前提是你的路由器已经开启了DHCP) 修改网卡配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens32 (最后一个为网卡名称) 动态 ...
- 【转】Unity3d的单例及场景间的数据传递
http://blog.csdn.net/zy19940906/article/details/47724387 单例是场景间切换时传递数据的最常见的方式之一,在unity中,很多方法被封装,有时候 ...
- 【bzoj4012】[HNOI2015]开店 动态点分治+STL-vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非常好啦,但是她们也发现她们面临着一个问题 ...
- tcp协议 tcpip协议 http协议,IP,DNS,端口号
每当看到HTTP协议,tcp/ip协议,TCP协议总是蒙圈:在这里先记录一下,方面自己查看 TCP协议:TCP(Transmission Control Protocol 传输控制协议)是一种面向连接 ...
- CSA Round #84 The Sprawl
题目 Analysis 曼哈顿距离($L1$ metric)最小生成树. Implementation 下面的代码参考了 gispzjz 在比赛中的提交. #include <bits/stdc ...
- POJ 2723 Get Luffy Out(2-SAT+二分答案)
Get Luffy Out Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8851 Accepted: 3441 Des ...
- 321. Create Maximum Number 解题方法详解
321. Create Maximum Number 题目描述 Given two arrays of length m and n with digits 0-9 representing two ...
- 【CCF】JSON查询
#include<iostream> #include<cstdio> #include<string> #include<cstring> #incl ...
- python请求带cookie
先获得cookie到文件 import cookielib import urllib2 #设置保存cookie的文件,同级目录下的cookie.txt filename = 'cookie.txt' ...
- div中div水平垂直居中
方法-1 img { vertical-align: middle; } div:before { content: ""; display: inline-block; widt ...