数据结构Java实现02----线性表与顺序表

简介:

【正文】

本节内容:

  • 线性结构
  • 线性表抽象数据类型
  • 顺序表
  • 顺序表应用

 

一、线性结构

如果一个数据元素序列满足:

(1)除第一个和最后一个数据元素外,每个数据元素只有一个前驱数据元素和一个后继数据元素

(2)第一个数据元素没有前驱数据元素;

(3)最后一个数据元素没有后继数据元素。

则称这样的数据结构为线性结构。

 

二、线性表抽象数据类型:

1、线性表抽象数据类型的概念:

线性表抽象数据类型主要包括两个方面:既数据集合和该数据集合上的操作集合。

数据集合:

  可以表示为a0,a1,a2,...an-1,每个数据元素的数据类型可以是任意的类型。

操作集合包括如下:

1.求元素个数

2.插入

3.删除

4.查找

5.判断是否为空

2、设计线性表抽象数据类型的Java接口:

代码如下:

复制代码
//线性表接口
public interface List {
    //获得线性表长度
    public int size();
    //判断线性表是否为空
    public boolean isEmpty();
    //插入元素
    public void insert(int index,Object obj) throws Exception;
    //删除元素
    public void delete(int index) throws Exception;
    //获取指定位置的元素
    public Object get(int index) throws Exception;
}
复制代码

然后我们让子类去实现这个接口就行了。

 

三、顺序表:(在物理存储结构上连续,大小固定)

1、顺序表的概念:

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

d3384f05-39d1-46d9-a580-bf4b531d740c

Java内存中,栈内存和堆内存占了很大一部分空间:栈内存的存储是顺序结构,堆内存的存储是离散结构。

 

2、设计顺序表类:

我们在上面第二段的List接口基础之上,设计一个顺序表:

(1)List.java:(线性表,和上面的第二段中代码一样)

复制代码
//线性表接口
public interface List {
    //获得线性表长度
    public int size();
    //判断线性表是否为空
    public boolean isEmpty();
    //插入元素
    public void insert(int index, Object obj) throws Exception;
    //删除元素
    public void delete(int index) throws Exception;
    //获取指定位置的元素
    public Object get(int index) throws Exception;
}
复制代码

(2)SequenceList.java:(核心代码)

复制代码
 1 public class SequenceList implements List {
 2 
 3     //默认的顺序表的最大长度
 4     final int defaultSize = 10;
 5     //最大长度
 6     int maxSize;
 7     //当前长度
 8     int size;
 9     //对象数组
10     Object[] listArray;
11 
12 
13     public SequenceList() {
14         init(defaultSize);
15     }
16 
17     public SequenceList(int size) {
18         init(size);
19     }
20 
21     //顺序表的初始化方法
22     private void init(int size) {
23         maxSize = size;
24         this.size = 0;
25         listArray = new Object[size];
26     }
27 
28     @Override
29     public void delete(int index) throws Exception {
30         // TODO Auto-generated method stub
31         if (isEmpty()) {
32             throw new Exception("顺序表为空,无法删除!");
33         }
34         if (index < 0 || index > size - 1) {
35             throw new Exception("参数错误!");
36         }
37         //移动元素
38         for (int j = index; j < size - 1; j++) {
39             listArray[j] = listArray[j + 1];
40         }
41         size--;
42     }
43 
44     @Override
45     public Object get(int index) throws Exception {
46         // TODO Auto-generated method stub
47         if (index < 0 || index >= size) {
48             throw new Exception("参数错误!");
49         }
50         return listArray[index];
51     }
52 
53     @Override
54     public void insert(int index, Object obj) throws Exception {
55         // TODO Auto-generated method stub
56         //如果当前线性表已满,那就不允许插入数据
57         if (size == maxSize) {
58             throw new Exception("顺序表已满,无法插入!");
59         }
60         //插入位置编号是否合法
61         if (index < 0 || index > size) {
62             throw new Exception("参数错误!");
63         }
64         //移动元素
65         for (int j = size - 1; j >= index; j--) {
66             listArray[j + 1] = listArray[j];
67         }
68 
69         listArray[index] = obj;  //不管当前线性表的size是否为零,这句话都能正常执行,即都能正常插入
70         size++;
71 
72     }
73 
74     @Override
75     public boolean isEmpty() {
76         // TODO Auto-generated method stub
77         return size == 0;
78     }
79 
80     @Override
81     public int size() {
82         // TODO Auto-generated method stub
83         return size;
84     }
85 }
复制代码

我们来看一下第54行的插入操作insert()方法:如果需要在index位置插入一个数据,那么index后面的元素就要整体往后移动一位。这里面需要特别注意的是:

插入操作:移动元素时,要从后往前操作,不能从前往后操作,不然元素会被覆盖的

删除元素:移动元素时,要从前往后操作。

(3)测试类:

复制代码
public class Test {

    public static void main(String[] args) {

        SequenceList list = new SequenceList(20);

        try {
            list.insert(0, 100);
            list.insert(0, 50);
            list.insert(1, 20);

            for (int i = 0; i < list.size; i++) {
                System.out.println("第" + i + "个数为" + list.get(i));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

我们要注意插入的规则是什么,不然会觉得这个顺序表打印输出的顺序很奇怪。

运行效果:

0e1ffa91-ced8-4e2a-b247-9d19b51b2c19

  

3、顺序表效率分析:

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

4、顺序表的优缺点:

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

 

5、顺序表的应用:

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

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

代码实现:

(1)List.java:

  和上面的代码保持不变

(2)SequenceList.java:

  和上面的代码保持不变

(3)Students.java:学生类

复制代码
//学生类
public class Students {

    private String id;// 学号
    private String name;// 姓名
    private String gender;// 性别
    private int age;// 年龄

    public Students() {

    }

    public Students(String sid, String name, String gender, int age) {
        this.id = sid;
        this.name = name;
        this.gender = gender;
        this.age = age;
    }


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "学号:" + this.getId() + " 姓名:" + this.getName() + " 性别:" + this.getGender() + " 年龄:" + this.getAge();
    }

}
复制代码

(4)Test.java:

复制代码
 1 public class Test {
 2 
 3     /**
 4      * @param args
 5      */
 6     public static void main(String[] args) {
 7         // TODO Auto-generated method stub
 8         SequenceList list = new SequenceList(100);
 9 
10         try {
11             list.insert(list.size, new Students("S0001", "张三", "男", 18)); //第一个参数list.size代表的是:我每次都是在顺序表的最后一个位置(当前线性表的长度的位置)进行插入操作。这一行里,size是等于0
12             list.insert(list.size, new Students("S0002", "李四", "男", 19));
13             list.insert(list.size, new Students("S0003", "王五", "女", 21));
14 
15             for (int i = 0; i < list.size; i++) {
16                 System.out.println(list.get(i));
17             }
18 
19         } catch (Exception ex) {
20             ex.printStackTrace();
21         }
22     }
23 
24 }
复制代码

注意第11行的注释:第一个参数list.size代表的是:我每次都是在顺序表的最后一个位置(当前线性表的长度的位置)进行插入操作;这样的话,遍历时才是按照张三、李四、王五的顺序进行输出的。

运行效果:

b0ccde4d-daf2-42c6-91e3-4f2f7a4e4b61

相关文章
|
1月前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
44 1
|
16天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
36 6
|
22天前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
25天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
25天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
56 3
|
25天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
30天前
|
存储 算法 Java
Java 中常用的数据结构
【10月更文挑战第20天】这些数据结构在 Java 编程中都有着广泛的应用,掌握它们的特点和用法对于提高编程能力和解决实际问题非常重要。
30 6
|
1月前
|
存储 Java 开发者
Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效
【10月更文挑战第19天】在软件开发中,随着项目复杂度的增加,数据结构的组织和管理变得至关重要。Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,帮助开发者告别混乱,提升代码质量。
29 1
|
25天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之王道第2.3章节之线性表精题汇总二(5)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
IKU达人之数据结构与算法系列学习×单双链表精题详解、数据结构、C++、排序算法、java 、动态规划 你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
22天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
109 9
下一篇
无影云桌面