一、线性表
线性表是n个具有相同特征的数据元素的有限序列,它是一种在实际中广泛使用的数据结构,常见的线性表有:顺序表、链表、栈、队列......
如图:顺序表与链表的区别看了标题的伙伴就应该知道,我们这次要讲解的主角是顺序表,所以链表等下次再来介绍了!
二、实现顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的数据结构,一般情况下采用数组存储,不过,它在数组上完成了数据的增删查改!
1、实现过程中的各种文件
如图:为了是实现这个顺序表,我创建了一个arrayList包,这个包底下有三个文件:
IList接口、MyArrayLIst类、Test类。
ILIst接口:接口中包含实现数据增删查改的功能,当然,接口中的方法不需要具体实现!
MyArrayList类:这个类定义了数组这个成员变量,并且具体实现了接口中的每一种功能!
Test类:这个类主要是来使用这个数据结构的,里面包含main方法!
2、MyArist类:
MyArrayList 全部代码:
package arrayList;
import java.util.Arrays;
//具体实现接口中的功能
public class MyArrayList implements IList {
//定义成员变量
public int[] elem;
public int useSize;
//创建构造方法
public MyArrayList(){
this.elem=new int[10];
this.useSize=0;
}
//在数组末尾添加数据
public void add(int data){
//判断数组是否满了?
//未满:将数据存入数组elem[useSize]处,同时useSize++
//满了:先扩容,再存放数据
if(isFull()){
//拷贝数组
elem= Arrays.copyOf(elem,2*elem.length);
}
this.elem[useSize]=data;
useSize++;
}
//判断数组是否满了
public boolean isFull(){
return useSize==elem.length;
}
//在指定位置添加数据
public void add(int data,int pos){
//判断pos的合理性
try{
checkPos(pos);
}catch (PosNotLegalException e){
e.printStackTrace();
}
//判断数组是否满了
if(isFull()){
elem=Arrays.copyOf(elem,2*elem.length);
}
for (int i = useSize-1; i <=pos ; i++) {
elem[i+1]=elem[i];
}
elem[pos]=data;
useSize++;
}
//判断pos是否合法?
private void checkPos(int pos){
if(pos<0||pos>useSize){
throw new PosNotLegalException("pos不合法!");
}
}
//判断是否包含某个元素
public boolean contains(int toFind){
for (int i = 0; i < useSize; i++) {
if(elem[i]==toFind){
return true;
}
}
return false;
}
//查找某个元素的位置
public int indexOf(int toFind){
for (int i = 0; i < useSize; i++) {
if(elem[i]==toFind){
return i;
}
}
return -1;
}
//获取pos位置的值
public int get(int pos){
try{
checkPosGetAndSet(pos);
}catch (PosNotLegalException e){
e.printStackTrace();
}
return elem[pos];
}
//判断get 的pos是否合法?
private void checkPosGetAndSet(int pos) {
if(pos<0||pos>=useSize){
throw new PosNotLegalException("pos不合法!");
}
}
//打印顺序表:
public void display(){
for (int i = 0; i < useSize; i++) {
System.out.print(elem[i]+" ");
}
System.out.println();
}
//将pos位置的值设置为value
public void set(int value,int pos){
try{
checkPosGetAndSet(pos);
}catch (PosNotLegalException e){
e.printStackTrace();
}
elem[pos]=value;
}
//去除指定元素
public void toRemove(int toRemove){
//如果找不到元素,返回
int pos=indexOf(toRemove);
if(pos==-1){
return;
}
//如果找到,去除元素
for (int i=pos;i<useSize-1;i++){
elem[i]=elem[i+1];
}
useSize--;
}
//去除数组内容
public void clear(){
useSize=0;
}
}
在数组末尾增加数据:
在数组末尾增加数据的功能很简单:
它的逻辑是,先使用isFull方法判断数组空间是否满了?如果未满:将数据添加到elem[useSize]处,同时useSize++;如果满了,就先給数组扩容,再添加数据到数组末尾!
具体实现:
//在MyArrlist类中:
//在数组末尾添加数据
public void add(int data){
//判断数组是否满了?
//未满:将数据存入数组elem[useSize]处,同时useSize++
//满了:先扩容,再存放数据
if(isFull()){
//拷贝数组
elem= Arrays.copyOf(elem,2*elem.length);
}
this.elem[useSize]=data;
useSize++;
}
//判断数组是否满了
public boolean isFull(){
return useSize==elem.length;
}
在指定位置插入数据:
在指定位置添加数据也不难,它的逻辑如下:只要我们将 从数组末尾到pos位置 的元素都往后挪动一个位置,到最后它就会将数组下标为pos的位置空出来,这样我们就可以添加我们需要添加的元素了!
但是在此之前,我们需要判断pos的合法性:
1、pos不能小于0,因为数组的下标最小为0
2、pos不能大于当前的useSize
还有一种情况:当数组空间满了的情况下,要先给数组扩容
具体实现:
这里我实现了一个功能,如果输入的pos不合法:抛出异常!(异常的知识可以在我的其他文章中寻找)
那么,我们就需要另外创建一个异常类:
//在MyArrayList类中:
//在指定位置添加数据
public void add(int data,int pos){
//判断pos的合理性:如果不合理,抛出异常!
try{
checkPos(pos);
}catch (PosNotLegalException e){
e.printStackTrace();
}
//判断数组是否满了
if(isFull()){
elem=Arrays.copyOf(elem,2*elem.length);
}
for (int i = useSize-1; i <=pos ; i++) {
elem[i+1]=elem[i];
}
elem[pos]=data;
useSize++;
}
//判断pos是否合法?
private void checkPos(int pos){
if(pos<0||pos>useSize){
throw new PosNotLegalException("pos不合法!");
}
这里给大家看看异常的效果:如果输入的pos不合法:
判断是否包含某个元素:
这个方法的主要逻辑是:通过循环遍历数组,如果找到要查找的元素,返回true,否则返回false
具体实现:
//在MyArrayList类中
//判断是否包含某个元素
public boolean contains(int toFind){
for (int i = 0; i < useSize; i++) {
if(elem[i]==toFind){
return true;
}
}
return false;
}
查找某个元素的位置:
这个方法的主要逻辑是:通过循环遍历数组,如果找到要查找的元素,返回其下标,否则返回一个负数
具体实现:
//在MyArrayList类中:
//查找某个元素的位置
public int indexOf(int toFind){
for (int i = 0; i < useSize; i++) {
if(elem[i]==toFind){
return i;
}
}
return -1;
}
获取pos位置的值:
这个方法的逻辑很简单:先判断传入的pos是否合法?不合法则抛出异常!合法则返回该下标的数组元素的值!
具体实现:
//在MyArrayList类中:
//获取pos位置的值
public int get(int pos){
try{
checkPosGetAndSet(pos);
}catch (PosNotLegalException e){
e.printStackTrace();
}
return elem[pos];
}
//判断get 的pos是否合法?
private void checkPosGetAndSet(int pos) {
if(pos<0||pos>=useSize){
throw new PosNotLegalException("pos不合法!");
}
}
打印顺序表:
具体实现:
//在MyArrayList类中:
//打印顺序表:
public void display(){
for (int i = 0; i < useSize; i++) {
System.out.print(elem[i]+" ");
}
System.out.println();
}
将pos位置的值设置为value:
具体实现:
//在MyArrayList类中:
//将pos位置的值设置为value
public void set(int value,int pos){
try{
checkPosGetAndSet(pos);
}catch (PosNotLegalException e){
e.printStackTrace();
}
elem[pos]=value;
}
去除pos位置的元素:
该方法的逻辑如下:
1、先看看能不能找到你要查找的元素,如果不能找到,return
如果可以找到,去除元素
2、去除元素原理:
从pos位置的元素开始,依次使当前元素的值等于下一个元素的值,然后i加1,直到i<useSIze
具体实现:
//去除指定元素
public void toRemove(int toRemove){
//如果找不到元素,返回
int pos=indexOf(toRemove);
if(pos==-1){
return;
}
//如果找到,去除元素
for (int i=pos;i<useSize-1;i++){
elem[i]=elem[i+1];
}
useSize--;
}
去除数组:
具体实现:
//去除数组内容
public void clear(){
useSize=0;
}
3、IList接口:
package arrayList;
//在这个接口实现数据的增删查改操作
public interface IList {
//在数组末尾增加数据
void add(int data);
boolean isFull();
//在指定位置添加元素
void add(int data,int pos);
//判断是否包含某个元素
boolean contains(int toFind);
//查找某个元素的位置
int indexOf(int toFind);
//获取pos位置的值
int get(int pos);
//打印顺序表:
void display();
//将pos位置的值设置为value
void set(int value,int pos);
//去除指定元素
void toRemove(int toRemove);
//去除数组内容
void clear();
}