转自https://www.cnblogs.com/smyhvae/p/4758808.html
【正文】
本节内容:
一、线性结构:
如果一个数据元素序列满足:
(1)除第一个和最后一个数据元素外,每个数据元素只有一个前驱数据元素和一个后继数据元素;
(2)第一个数据元素没有前驱数据元素;
(3)最后一个数据元素没有后继数据元素。
则称这样的数据结构为线性结构。
二、线性表抽象数据类型:
1、线性表抽象数据类型的概念:
线性表抽象数据类型主要包括两个方面:既数据集合和该数据集合上的操作集合。
数据集合:
可以表示为a0,a1,a2,...an-1,每个数据元素的数据类型可以是任意的类型。
操作集合包括如下:
1.求元素个数
2.插入
3.删除
4.查找
5.判断是否为空
2、设计线性表抽象数据类型的Java接口:
代码如下:
package com.songdan.list;
//线性表接口类
public interface List {
//获得线性表长度
public int ListLength();
//判断线性表是否为空
public boolean ListEmpty();
//插入元素
public void ListInsert(int index,Object obj) throws Exception;
//删除元素
public Object ListDelete(int index) throws Exception;
//获取指定位置的元素
public Object GetElement(int index) throws Exception;
}
然后我们让子类去实现这个接口就行了。
package com.songdan.sequencelist;
import com.songdan.list.List;
import com.sun.accessibility.internal.resources.accessibility;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class SequenceList implements List{
//线性表的默认长度
private final int DefaultSize = 10;
//最大长度
private int MaxSize;
//当前长度
private int size;
Object []listArray;
public SequenceList(){
init(DefaultSize);
}
public SequenceList(int num){
init(num);
}
//初始化方法
public void init(int size) {
this.MaxSize = size;
this.size = 0;
listArray = new Object[size];
}
public Object GetElement(int index) throws Exception{
if(index < 0 || index >= size)
throw new Exception("参数错误");
else return listArray[index];
}
@Override
public Object ListDelete(int index) throws Exception{
//空链表
if (size == 0) {
throw new Exception("空链表");
}
//下标不正确
else if(index < 0 || index >= size){
throw new Exception("参数不正确");
}
//链表移动
else {
Object obj = listArray[index];
for(int i = index;i+1 < size;i++){
listArray[i] = listArray[i+1];
}
size--;//大小要减1
return obj;
}
}
@Override
public void ListInsert(int index, Object obj) throws Exception {
//当前线性表已满,不能插入
if(size == MaxSize)
throw new Exception("线性表已满,无法插入");
//插入位置是否合法
else if(index < 0 || index > size){
throw new Exception("参数不正确");
}
else {
for (int i = index; i < size; i++) {
listArray[i+1] = listArray[i];
}
listArray[index] = obj;
}
size++;
}
@Override
public int ListLength() {
return size;
}
@Override
public boolean ListEmpty() {
return size == 0;
}
//遍历表
public void TraveList(){
int i = 0;
for (Object obj : listArray) {
System.out.println("第" + i++ + "个元素是" + obj );
if(i==size)
break;
}
}
}
三、顺序表:(在物理存储结构上连续,大小固定)
1、顺序表的概念:
计算机有两种基本的存储结构(物理存储结构):顺序结构、离散结构。使用顺序结构实现的线性表称为顺序表。如下图所示:
Java内存中,栈内存和堆内存占了很大一部分空间:栈内存的存储是顺序结构,堆内存的存储是离散结构。
2、设计顺序表类:
我们在上面第二段的List接口基础之上,设计一个顺序表:
(1)List.java:(线性表,和上面的第二段中代码一样)
package com.songdan.list;
//线性表接口类
public interface List {
//获得线性表长度
public int ListLength();
//判断线性表是否为空
public boolean ListEmpty();
//插入元素
public void ListInsert(int index,Object obj) throws Exception;
//删除元素
public Object ListDelete(int index) throws Exception;
//获取指定位置的元素
public Object GetElement(int index) throws Exception;
}
(2)SequenceList.java:(核心代码)
package com.songdan.sequencelist;
import com.songdan.list.List;
public class SequenceList implements List{
//线性表的默认长度
private final int DefaultSize = 10;
//最大长度
private int MaxSize;
//当前长度
private int size;
Object []listArray;
public SequenceList(){
init(DefaultSize);
}
public SequenceList(int num){
init(num);
}
//初始化方法
public void init(int size) {
this.MaxSize = size;
this.size = 0;
listArray = new Object[size];
}
public Object GetElement(int index) throws Exception{
if(index < 0 || index >= size)
throw new Exception("参数错误");
else return listArray[index];
}
@Override
public Object ListDelete(int index) throws Exception{
//空链表
if (size == 0) {
throw new Exception("空链表");
}
//下标不正确
else if(index < 0 || index >= size){
throw new Exception("参数不正确");
}
//链表移动
else {
Object obj = listArray[index];
for(int i = index;i+1 < size;i++){
listArray[i] = listArray[i+1];
}
size--;//大小要减1
return obj;
}
}
@Override
public void ListInsert(int index, Object obj) throws Exception {
//当前线性表已满,不能插入
if(size == MaxSize)
throw new Exception("线性表已满,无法插入");
//插入位置是否合法
else if(index < 0 || index > size){
throw new Exception("参数不正确");
}
else {
for (int i = index; i < size; i++) {
listArray[i+1] = listArray[i];
}
listArray[index] = obj;
}
size++;
}
@Override
public int ListLength() {
return size;
}
@Override
public boolean ListEmpty() {
return size == 0;
}
//遍历表
public void TraveList(){
int i = 0;
for (Object obj : listArray) {
System.out.println("第" + i++ + "个元素是" + obj );
if(i==size)
break;
}
}
}
我们来看一下第54行的插入操作insert()方法:如果需要在index位置插入一个数据,那么index后面的元素就要整体往后移动一位。这里面需要特别注意的是:
插入操作:移动元素时,要从后往前操作,不能从前往后操作,不然元素会被覆盖的。
删除元素:移动元素时,要从前往后操作。
(3)测试类:
package com.songdan.sequencelist;
import com.songdan.student.Student;
public class TestSL {
public static void main(String[] args) throws Exception {
SequenceList sequenceList = new SequenceList(10);
sequenceList.ListInsert(0, 100);
sequenceList.ListInsert(1, "hahh1");
sequenceList.ListInsert(2, 600);
sequenceList.ListInsert(3, "年后");
sequenceList.TraveList();
}
}
我们要注意插入的规则是什么,不然会觉得这个顺序表打印输出的顺序很奇怪。
运行效果:
3、顺序表效率分析:
4、顺序表的优缺点:
5、顺序表的应用:
设计一个顺序表,可以保存100个学生的资料,保存以下三个学生的资料,并打印输出。
代码实现:
(1)List.java:
和上面的代码保持不变
(2)SequenceList.java:
和上面的代码保持不变
(3)Students.java:学生类
package com.songdan.student;
public class Student {
private String name;
private String num;
private int age;
private char sex;
public Student(String num, String name, char sex,int age) {
super();
this.name = name;
this.num = num;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
@Override
public String toString() {
return "student [age=" + age + ", name=" + name + ", num=" + num
+ ", sex=" + sex + "]";
}
}
(4)Test.java:
package com.songdan.sequencelist;
import com.songdan.student.Student;
public class TestSL {
public static void main(String[] args) throws Exception {
SequenceList sequenceList = new SequenceList(10);
sequenceList.ListInsert(0, new Student("张三","S00001",'男',18));
sequenceList.ListInsert(1, new Student("李四","S00002",'男',19));
sequenceList.ListInsert(2, new Student("王五","S00003",'女',20));
sequenceList.TraveList();
}
}
运行效果: