一、概念

对于常用的数据结构,可分为线性结构和非线性结构,线性结构主要是线性表,非线性结构主要是数和图。当n>0时,表可表示为:(a0,a1,a2,a3,…an)

1、 线性表的特征:

1、存在唯一的被称作”第一个”的数据元素

2、存在唯一的一个称作”最后一个的”数据元素”

3、除第一个之外,集合中的每个数据元素均只有一个前驱

4、除最后一个之外,集合中每个元素均只有一个后继

2、线性表的基本操作

1、初始化:

2、返回线性表长度

3、获取指定索引处元素

4、按值查找元素位置

5、直接插入数据元素

6、向指定位置插入元素

7、直接删除元素

8、删除指定位置元素

二、顺序存储结构

线性表的顺序结构是指用一组地址连续的存储单元依次存放线性表的元素。下面采用数组实现顺序结构线性表。

 import java.util.Arrays;
public class Sequence<T> {
privateObject[] elementData;//定义一个数组
privateint DEFAULT_SIZE = 1; //数组默认大小
privateint capacity; //数组容量
privateint size = 0; //当前数组大小
//初始化
public Sequence(){
capacity= this.DEFAULT_SIZE;
elementData= new Object[capacity];
} public Sequence()(T element){
this();
elementData[0]= element;
size++;
} //返回线性表长度
public int length(){
return this.size;
} //返回指定索引处元素。
public T getElementByIndex(int index){ if(index< 0 || index > (size-1)){
System.out.println("索引范围越界!!!");
System.exit(0);
}
return (T)elementData[index];
}
//按值查找数据元素的位置
public int getIndexByValue(T value){
for(int i = 0; i < elementData.length;i++ ){
if(value.equals(elementData[i])){
return i;
}
}
return -1;//未找到则返回-1
} //向指定位置插入元素
public void insert(T element,int index){
ensureCapacity(); //确保线性表容量够
if(index>= 0 && index < size){
int i = 0;
//将插入位置之后元素挨个后移1
for(i= (size-1); i >= index;i--){
elementData[i+1]= elementData[i];
}
elementData[i+1]= element;//插入该元素
size++; //数组当前容量+1
}
else{
throw new IndexOutOfBoundsException("插入元素位置越界!!!");
}
} //想线性表末尾添加元素
public void add(T element){
ensureCapacity(); //确保线性表容量够
elementData[size]= element;
size++;
} //删除线性表中指定位置元素
public void delete(int index){
if(index>= 0 && index < size){
int i;
//将要删除元素位置之后的元素挨个前移1,通过覆盖删除
for(i= index+1;i < size;i++){
elementData[i-1]= elementData[i];
}
elementData[size-1]= null;
}
else{
thrownew IndexOutOfBoundsException("所要删除元素位置越界!!!");
}
} //删除指定元素
public void delete(T value){
int index = this.getIndexByValue(value);
if(index!= -1){
this.delete(index);
}
else{
System.out.println("您要删除的元素并不存在");
System.exit(0);
}
size--;
} //判断线性表是否为空
public boolean isEmpty(){
boolean b = false;
if(this.length()!= 0){
b= true;
}
return b;
} //清空线性表
public void clear(){
for(Object o:elementData){
o= null;
}
size= 0;
} //显示线性表中所有元素
public void view(){
System.out.print("当前线性表中元素为:");
for(int i = 0;i < size;i++){
System.out.print(elementData[i]+ " ");
}
System.out.print("\n");
} //扩充线性表容量
public void ensureCapacity(){
while((size+1)> capacity){
capacity=capacity * 2; //线性表容量每次增大一倍
elementData= Arrays.copyOf(elementData, capacity);
}
} public static void main(String[] args) {
Sequence<String> sequence = new Sequence<>();
sequence.add("hello");
sequence.add("world");
sequence.add("java");
sequence.add("perfect");
sequence.view();
sequence.insert("haha",1);
sequence.view();
System.out.println("索引为3的元素为:" +sequence.getElementByIndex(3));
System.out.println("字符串perfect的索引号为:"+ sequence.getIndexByValue("perfect"));
sequence.delete("hello");
sequence.view();
sequence.clear();
System.out.println("clear之后线性表长度为:"+ sequence.length());
}
}

三、链式存储结构

1、概念

链式存储结构的线性表(简称为链表)采用一组任意的存储单元存放线性表中的数据元素。链式存储结构的线性表不是按线性的逻辑顺序来保存数据元素,它需要在每个数据元素里保存一个引用下一个数据元素的引用。

节点 = 数据元素 + 引用下一个节点的引用 + 引用上一个节点的引用

2、单链表基本操作

建立单链表方法:1头插法建表  2尾插法建表

查找操作:1按index查找指定数据元素  2在链表中查找指定的数据元素的index

插入操作:在第index个索引处插入元素

删除操作:删除第index个节点

3、单链表具体实现

 public class  LinkList<T>{
//定义Node节点
private class Node{
private T data;
private Node next; public Node(){ }
public Node(T element,Node next){
this.data= element;
this.next= next;
}
}
//成员变量
private Node header;//头节点
private Node tail; //尾节点
private int size = 0; //链表长度 public LinkList(){
header= null;
tail= header;
} public LinkList(T element){
header= new Node(element,null);
tail= header;
} //获取链表中指定索引处的元素
public T get(int index){
return this.getNodeByIndex(index).data;
} //获取链表中指定索引处Node
public Node getNodeByIndex(int index){
this.checkBorder(index);
Node currentNode = header;
for(int i = 0;i < size && currentNode !=null;i++,currentNode =currentNode.next){
if(i== index){
return currentNode;
}
}
return null;
} //向指定索引处插入元素
public void insert(T element,int index){
this.checkBorder(index);
if(index== 0){
this.addAtHeader(element);
}
else{
NodeprevNode =this.getNodeByIndex(index-1);//获取插入位置的前向Node
prevNode.next=new Node(element,prevNode.next);
}
size++;
} //删除指定索引处Node
public T delete(int index){
this.checkBorder(index);
Nodedel = null;
//删除的是header
if(index== 0){
del= header;
header= header.next;
}
else{
NodeprevNode =this.getNodeByIndex(index);
del= prevNode.next;
prevNode.next= del.next; //将prevNode的后向Node设置为del.next
del.next= null;
}
size--;
returndel.data;
} //头插法向链表中添加元素
public void addAtHeader(T element){
header= new Node(element,header);//将新添加的Node的next设置为原先的header,然后将新的Node设置为新的header
if(tail==null){
tail= header;
}
size++;
} //尾插法
public void add(T element){
//链表为空的情况
if(header==null){
header= new Node(element,null);
tail= header;
}
else{
tail.next= new Node(element, null); //将tail节点的next设置为new Node
tail= tail.next;//将new Node设置为tail
}
size++;
}
//遍历整个链表
public void view(){
NodecurrentNode = header;
System.out.print("当前链表元素:");
while(currentNode!=null){
System.out.print(currentNode.data+ " ");
currentNode= currentNode.next;
}
System.out.println(""); } //检测索引是否越界
private void checkBorder(int index){
if(index< 0 || index > size-1){
thrownew IndexOutOfBoundsException("链表索引已越界");
}
} public int length(){
return this.size;
} public static void main(String args[]){
LinkList<String> linkList =new LinkList<>();
linkList.add("hello");
linkList.add("world");
linkList.addAtHeader("header");
System.out.println("当前链表长度为:"+ linkList.length());
linkList.view();
System.out.print("插入test之后,");
linkList.insert("test",2);
linkList.view();
linkList.delete(2);
System.out.print("删除索引2处元素后,");
linkList.view();
System.out.println("索引1处元素为:" +linkList.get(1));
}
}

4、双链表实现

 public class  DoubleLinkList<T> {

          //定义双向链表节点
private class Node{
private T data;
private Node prev;
private Node next;
public Node(){ }
public Node(T element,Node prev,Node next){
this.data= element;
this.prev= prev;
this.next= next;
}
} private Node header;
private Node tail;
private int size = 0; public DoubleLinkList(){
header= null;
tail= null;
} public DoubleLinkList(T element){
header= new Node(element,null,null);
tail= header;
size++;
}
//获取链表长度
public int length(){
return this.size;
} //检测index是否越界
public void checkBorder(int index){
if(index< 0 || index > size-1){
throw new IndexOutOfBoundsException("链表索引已越界");
}
} //获取指定索引处Node
public Node getNodeByIndex(int index){
checkBorder(index);//越界检测
if(index< size/2){
NodecurrentNode = header;
for(int i = 0;i < size/2;i++,currentNode = currentNode.next ){
if(i== index){
return currentNode;
}
}
}
else{
NodecurrentNode = tail;
for(int i = size-1;i >= size/2;i--,currentNode = currentNode.prev){
if(i== index){
returncurrentNode;
}
}
}
return null;
} //获取链表中指定索引处的元素值
public T get(int index){
return this.getNodeByIndex(index).data;
} //根据元素值查找元素索引
public int locate(T element){
Node currentNode = this.header;
for(int i = 0;i < size-1;i++,currentNode = currentNode.next){
if(currentNode.data.equals(element)){
returni;
}
}
return -1; } //向链表中以尾插法添加元素
public void add(T element){
if(size== 0){
header= new Node(element,null,null);
tail= header;
}
else{
Node newNode =new Node(element,tail,null);
tail.next= newNode;
tail= newNode;
}
size++;
} //头插法向链表添加元素
public void addAtHeader(T element){
if(size== 0){
header= new Node(element,null,null);
tail= header;
}
else{
Node newNode =new Node(element,null,header);
header.prev= newNode;
header= newNode;
}
size++;
} //根据索引插入元素
public void insert(T element,int index){
this.checkBorder(index);
Node prevNode = this.getNodeByIndex(index-1);
Node nextNode = this.getNodeByIndex(index);
Node insertNode = new Node(element, prevNode, nextNode);
nextNode.prev= insertNode;
prevNode.next= insertNode;
size++;
} //根据索引删除元素
public void delete(int index){
this.checkBorder(index);
Node prevDelNode = this.getNodeByIndex(index-1);
Node nextDelNode = this.getNodeByIndex(index+1);
prevDelNode.next= nextDelNode;
nextDelNode.prev= prevDelNode;
size--;
} //遍历链表中元素
public void view(){
System.out.print("当前链表中元素为:");
for(int i = 0;i < size;i++){
System.out.print(this.get(i)+ " ");
}
System.out.println();
} public static void main(String[] args) {
DoubleLinkList<String> doubleLinkList =new DoubleLinkList<>();
doubleLinkList.add("hello");
doubleLinkList.add("world");
doubleLinkList.insert("test",1);
doubleLinkList.addAtHeader("first");
doubleLinkList.view();
System.out.println("索引为0处的元素值为:"+ doubleLinkList.get(0));
System.out.println("test字符串在链表中索引号为:" + doubleLinkList.locate("test"));
doubleLinkList.delete(1);
System.out.print("删除索引号为1元素后,");
doubleLinkList.view();
} }

注:本文部分内容参考自《疯狂Java程序员的基本修养》和《数据结构(C语言版)》

线性表的Java实现的更多相关文章

  1. 数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解

    数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解 对数组有不了解的可以先看看我的另一篇文章,那篇文章对数组有很多详细的解析,而本篇文章则着重讲动态数组,另一篇文章链接 ...

  2. 线性表 及Java实现 顺序表、链表、栈、队列

    数据结构与算法是程序设计的两大基础,大型的IT企业面试时也会出数据结构和算法的题目, 它可以说明你是否有良好的逻辑思维,如果你具备良好的逻辑思维,即使技术存在某些缺陷,面试公司也会认为你很有培养价值, ...

  3. 线性表(java)

    线性表 概念:零个或者多个数据元素的有限序列. 特点:除了第一个元素没有前驱结点,最后一个元素没有后继结点外,其它元素有且仅有一个直接前驱和一个直接后继结点.元素的个数必定为有限个. 实现: 定义一个 ...

  4. 线性表的Java实现--链式存储(双向链表)

    有了单向链表的基础,双向链表的实现就容易多了. 双向链表的一般情况: 增加节点: 删除节点: 双向链表的Java实现: package com.liuhao.algorithm;      publi ...

  5. 线性表的Java实现--链式存储(单向链表)

    单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始. 链式存储结构的线性表将采用一组任意的存储单元存放线性表中的数据元素.由于不需要按顺序存储,链表在 ...

  6. 常用数据结构-线性表及Java 动态数组 深究

    [Java心得总结六]Java容器中——Collection在前面自己总结的一篇博文中对Collection的框架结构做了整理,这里深究一下Java中list的实现方式 1.动态数组 In compu ...

  7. 数据结构(Java描述)之线性表

    基础概念 数据结构:是相互之间存在一种或多种关系的数据元素的集合. 逻辑结构和物理结构 关于数据结构,我们可以从逻辑结构和物理结构这两个维度去描述 逻辑结构是数据对象中数据元素之间的关系,是从逻辑意义 ...

  8. Java Se :线性表

    Java的集合框架分为两个系列,Collection和Map系列.在大学期间,学习数据结构时,好像学习了线性表.非线性表.树,哎,都给忘了.其实,在Collection系列内部又可以分为线性表.集合两 ...

  9. Java数据结构之线性表(2)

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

随机推荐

  1. First Missing Positive 解答

    Question Given an unsorted integer array, find the first missing positive integer. For example,Given ...

  2. Count Primes 解答

    Question Count the number of prime numbers less than a non-negative number, n. Solution 1 Naive way, ...

  3. LeeCode(Database)-Employees Earning More Than Their Managers

    The Employee table holds all employees including their managers. Every employee has an Id, and there ...

  4. HDOJ-1014 Uniform Generator

    http://acm.hdu.edu.cn/showproblem.php?pid=1014 给出式子seed(x+1) = [seed(x) + STEP] % MOD seed初始为0,给出STE ...

  5. linux添加静态路由表,重启继续生效(转载)

    在日常的使用中,或者在服务器中,有两个网卡配置两个地址,访问不同的网络段,这种情况是非常常见的现象,但是,我们需要额外的添加路由表来决定发送的数据包经过正确的网关和interface才能正确的进行通信 ...

  6. CDH 2、Cloudera Manager的安装

    1.Cloudera Manager • Cloudera Manager是一个管理CDH的端到端的应用. • 作用: – 管理 – 监控 – 诊断 – 集成 • 架构 • Server – 管理控制 ...

  7. java concurrent 之 SynchronousQueue

    Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除操作take,反过来也一样. 不像Arra ...

  8. Win7窗口操作

    1.使用 Aero Shake 晃动最小化打开的窗口您可以使用 Aero Shake 晃动将所有打开的窗口快速最小化,只剩下您需要使用的窗口.然后,还可以轻松还原所有窗口.操作方法如下:1. 在需要保 ...

  9. 关于JS变量和作用域

    ECMAScript 变量:1.基本类型值(简单数据段) 2.引用类型值(可能由过个值构成的对象) → 保存在内存中的对象 动态属性: 只能给引用型值动态添加新属性,以便将来使用. 复制变量值 : 基 ...

  10. Apache的httpd命令详解

    Apache的httpd命令详解 来源:全栈开发者 发布时间:2012-01-03 阅读次数:10965 4   httpd.exe为Apache HTTP服务器程序.直接执行程序可启动服务器的服务. ...