数据结构之 java 顺序表实现

转自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、顺序表的概念:

计算机有两种基本的存储结构(物理存储结构):顺序结构、离散结构。使用顺序结构实现的线性表称为顺序表。如下图所示:

d3384f05-39d1-46d9-a580-bf4b531d740c

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、顺序表效率分析:

  • 顺序表插入和删除一个元素的时间复杂度为O(n)。
  • 顺序表支持随机访问,顺序表读取一个元素的时间复杂度为O(1)。因为我们是可以通过下标直接访问的,所以时间复杂度是固定的,和问题规模无关。

4、顺序表的优缺点:

  • 顺序表的优点是:支持随机访问;空间利用率高(连续分配,不存在空间浪费)。
  • 顺序表的缺点是:大小固定(一开始就要固定顺序表的最大长度)插入和删除元素需要移动大量的数据。

 

5、顺序表的应用:

设计一个顺序表,可以保存100个学生的资料,保存以下三个学生的资料,并打印输出。

0393f396-1a75-4b69-927f-3e923f86d207

代码实现:

(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();
	}

}

 

 

运行效果:

 

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值