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


    一、线性结构

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

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

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

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

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

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

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

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

    数据集合:

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

    操作集合包括如下:

    1.插入
    2.查找
    3.删除 

    4.判断是否为空
    5.求元素个数

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

    代码如下:

     1 package com.myutil.list;
     2 
     3 public interface List {
     4     //插入元素
     5     public void insert(int index,Object obj) throws Exception;
     6     //重载插入方法
     7     public void insert(Object obj) throws Exception;
     8     //获取指定位置的元素
     9     public Object get(int index) throws Exception;
    10     //删除元素
    11     public void delete(int index) throws Exception;
    12     //获得线性表长度
    13     public int size();
    14     //判断线性表是否为空
    15     public boolean isEmpty();
    16 }

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

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

    1、顺序表的概念:

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

    d3384f05-39d1-46d9-a580-bf4b531d740c

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

    2、设计顺序表类:

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

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

     1 package com.myutil.list;
     2 
     3 public interface List {
     4     //插入元素
     5     public void insert(int index,Object obj) throws Exception;
     6     //重载插入方法
     7     public void insert(Object obj) throws Exception;
     8     //获取指定位置的元素
     9     public Object get(int index) throws Exception;
    10     //删除元素
    11     public void delete(int index) throws Exception;
    12     //获得线性表长度
    13     public int size();
    14     //判断线性表是否为空
    15     public boolean isEmpty();
    16 }

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

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

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

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

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

    (3)测试类:

     1 package com.myutil.list;
     2 
     3 public class Test {
     4 
     5     public static void main(String[] args) {
     6 
     7         SequentialList list = new SequentialList(20);
     8 
     9         try {
    10             list.insert(0, 100);
    11             list.insert(0, 50);
    12             list.insert(1, 20);
    13             list.insert(60);
    14 
    15             for (int i = 0; i < list.size(); i++) {
    16                 System.out.println("第" + i + "个数为" + list.get(i));
    17             }
    18 
    19         } catch (Exception e) {
    20             e.printStackTrace();
    21         }
    22     }
    23 }

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

    运行效果:

    第0个数为50
    第1个数为20
    第2个数为100
    第3个数为60

    3、顺序表效率分析:

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

    4、顺序表的优缺点:

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

    5、顺序表的应用:

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

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

    代码实现:

    (1)List.java:

      和上面的代码保持不变

    (2)SequentailList.java:

      和上面的代码保持不变

    (3)Students.java:学生类

     1 package com.myutil.list.use;
     2 
     3 //学生类
     4 public class Students {
     5 
     6   private String id;// 学号
     7   private String name;// 姓名
     8   private String gender;// 性别
     9   private int age;// 年龄
    10 
    11   public Students() {
    12 
    13   }
    14 
    15   public Students(String sid, String name, String gender, int age) {
    16       this.id = sid;
    17       this.name = name;
    18       this.gender = gender;
    19       this.age = age;
    20   }
    21 
    22 
    23   public String getId() {
    24       return id;
    25   }
    26 
    27   public void setId(String id) {
    28       this.id = id;
    29   }
    30 
    31   public String getName() {
    32       return name;
    33   }
    34 
    35   public void setName(String name) {
    36       this.name = name;
    37   }
    38 
    39   public String getGender() {
    40       return gender;
    41   }
    42 
    43   public void setGender(String gender) {
    44       this.gender = gender;
    45   }
    46 
    47   public int getAge() {
    48       return age;
    49   }
    50 
    51   public void setAge(int age) {
    52       this.age = age;
    53   }
    54 
    55   public String toString() {
    56       return "学号:" + this.getId() + " 姓名:" + this.getName() + " 性别:" + this.getGender() + " 年龄:" + this.getAge();
    57   }
    58 
    59 }

    (4)Test.java:

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

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

    运行效果:

    学号:S0001 姓名:张三 性别:男 年龄:18
    学号:S0002 姓名:李四 性别:男 年龄:19
    学号:S0003 姓名:王五 性别:女 年龄:21
    学号:S0004 姓名:赵六 性别:女 年龄:20

    本文参考博客:http://www.cnblogs.com/smyhvae/p/4758808.html,并加入自己的一点改动,后续还会有优化改动,例如加入泛型等。。。。。。

  • 相关阅读:
    ArrayList用法
    MessageBox
    将文本文件导入Sql数据库
    在桌面和菜单中添加快捷方式
    泡沫排序
    Making use of localized variables in javascript.
    Remove double empty lines in Visual Studio 2012
    Using Operations Manager Connectors
    Clear SharePoint Designer cache
    Programmatically set navigation settings in SharePoint 2013
  • 原文地址:https://www.cnblogs.com/midiyu/p/8158395.html
Copyright © 2020-2023  润新知