【数据结构真不难】线性表——五一专属|向所有热爱分享的“技术劳动者”致敬

简介: 【数据结构真不难】线性表——五一专属|向所有热爱分享的“技术劳动者”致敬

1.概述


线性表:是一种最常用、最简单,也是最基本的数据结构。


线性表由n个数据元素所构成的有限序列,且数据类型相同。


线性表可以用顺序存储和链式存储两种存储结构来表示。


使用顺序存储的线性表称为顺序表,也称为静态线性表。


使用链式存储的线性表称为链表,也称为动态线性表。


链表的分类:单链表、双向链表、循环链表。


2.顺序表


2.1定义


顺序表,就是顺序存储的线性表。


顺序存储是用一组地址连续的存储单元依次存放线性表中各个数据元素的存储结构。


在逻辑上,数据ABCD是连续


在物理上,地址也是连续的微信图片_20220530203150.png

  • 可以使用数组来描述数据结构中的顺序存储结构。

2.2地址公式


地址公式

//第i的地址 = 第一个地址 + 第几个 *   存储单位Loc(ai)   =  Loc(a0) +    i   *   c


微信图片_20220530203155.png

2.3顺序表特点


在线性表中逻辑上相邻的数据元素,在物理存储位置上也是相邻的。


存储密度高。但需要预先分配“足够”的存储空间。


存储密度 = 数据元素存储空间 / 数据元素实际占用空间


在顺序表中,存储密度为1。


便于随机存储。(数组中可以通过下标进行存储)


不便于插入和删除操作。两种操作都会引起大量的数据移动。


2.4算法:插入


需要:在顺序表第i个位置处插入一个新元素。


顺序表插入操作:将第i个数据元素及其之后的所有的数据元素,后移一个存储位置,再将新元素插入到i处。

微信图片_20220530203321.png 前置:类中成员

public class SqList {
    private Object[] listElem;    //线性表的存储空间
    private int curLen;       //线性表的当前长度
}

插入操作算法

/**
 * @Param i 第i个位置
 * @Param x 需要插入的数据
 */
public void insert(){
    //0.1满校验:存放实际长度 和 数组长度一样
    if(curLen == listEle.length){
        throw new Exception("已满");
    }
    //0.2非法校验 在已有的数据中插入[0,curLen]必须连续 中间不能空元素
    if(i < 0 || i > curLen){
        throw new Exception("位置非法");
    }
    //1 将i及其之后移
    for(int j = curLen; j > i; j--){
        listEle[j] = listEle[j - 1];
    }
    //2 插入i处
    listEle[i] = x;
    //3 记录长度
    curLen++;
}
  • 插入时间复杂度:O(n)


2.5算法:删除


  • 需求:将第i位置处元素删除
  • 删除操作:将第i个数据元素ai之后的所有数据元素向前一定一个存储位置。微信图片_20220530203327.png

算法:

public void remove(int i){
    //0.1校验非法数据
    if(i < 0 || i > curLen - 1){
        throw new Exception("位置非法");
    }
    //1 将i之后向前移动
    for(int j = i; j < curLen - 1; j++){
        listEle[j] = listEle[j+1];
    }
    //2 长度--
    curLen--;
}
  • 删除时间复杂度:O(n)


 2.6算法:查找


  • 需求:查找指定数据的索引号
  • 算法1:循环遍历已有数据,进行判断,如果有返回第一个索引号,如果没有返回-1
public int indexOf(Object x){
    for(int i = 0; j < curLen; i++){
        if(listEle[i].equals(x)){
            return i;
        }
    }
    return -1;
}

算法2:使用变量记录没有匹配到索引

public int indexOf(Object x){
    int j = 0;    //用于记录索引信息
    while(j < curLen && !listEle[j].equals(x)){
        j++;
    }
    //j记录索引小于数量
    if(j < curLen){
        return j;
    }else{
        return -1;
    }   
}

查询时间复杂度:O(n)


       2.7顺序表局限性

若要为线性表扩充存储空间,则需要重新创建一个地址连续的更大的存储空间,并把原有的数据元素都复制到新的存储空间中。(扩容)


因为顺序存储要求逻辑上相邻的数据元素,在物理存储位置上也是相邻的,这就使得要增删数据元素时,会引起平均一半的数据元素的移动。


3.单链表


3.1定义


采用链式存储方式存储的线性表称为链表。


链表中每一个结点包含存放数据元素值的数据域和存放逻辑上相邻节点的指针域。


数据域 data:用于存放数据元素的值。


指针域 next:用于存放后继结点的地址。微信图片_20220530203659.png

3.2术语


非空表:微信图片_20220530203708.png

空表:空表的指针域为空指针null微信图片_20220530203750.png

3.3类定义


  • 数据域 data:用于存放数据元素的值。
  • 指针域 next:用于存放后继结点的地址。
public class Node{
    public Object data;       //数据域
    public Node next;       //指针域
}

3.4算法:【单链表的长度】

public int length(){
    Node p = head.next;        //获得第一个节点
    int length = 0;            //定义一个变量记录长度
    while(p != null){
         length++;            //计数
         p = p.next;          //p指向下一个节点
    }
    return length;
}

3.5算法:按索引号(位序号)查找


  • 思路:
  • 处理了所有的结点都没有数据,判断依据 null
  • 处理到一部分就找到了,判断依据
1public Object get(int i){
    Node p = head.next;                        //获得头节点
    int j = 0;
    while(p != null && j < i){                //已经处理的节点数
        p = p.next;                            //链表没有下一个 && 处理有效部分
        j++;
    }
    if(i < 0 || p == null){
        throw new Exception("元素不存在");
    }
    return p.data;    //返回数据
}

3.6算法:按值查找所以号


//查询给定值的索引号 如果没有返回-1
public int indexOf(Object x){
    Node p = head.next;        //获得头节点
    int j = 0;                //不匹配元素的个数
    while(p != null && !p.data.equals(x)){    //循环依次找[不匹配]元素
        p = p.next;
        j++;
    }
    //返回匹配索引 如果没有返回-1
    if(p != null){
        return j;
    }else{    
        return -1;
    }
}

 3.7算法:插入


  • 需求:向索引i前面插入一个新结点s
  • 思路:获得i的前驱,结点P
public void insert(int i,Object x){
    Node p = ......;            //获得i前驱
    Node s = new Node(x);       //创建新节点s
    s.next = p.next;            //必须先执行
    p.next = s;                //然后再执行
}

微信图片_20220530204001.png

3.8删除


需求:删除i结点微信图片_20220530204008.png

public void remove(int i){
    //获得i的前驱节点p
    p.next = p.next.next;
}

3.9获得前驱


// i最小值0,表示获得头结点head
// 算法内部,使用-1表示头结点head,结点移动从头结点head开始。
public void previous(int i){
    Node p = head;
    int j = -1;
    while(p != null && j < i - 1){
        p = p.next;
        j++;
    }
    if(p != null || i < 0){
        throw new RuntimeException("i不合法");
    }
}

4.循环链表


4.1定义


循环链表也称为环形链表,其结构与单链表相似,只是将单链表的首尾相连。微信图片_20220530204155.png

// p结点是尾结点
2. p.next = head;

4.2算法:循环链表合并


  • 分析微信图片_20220530204254.png


核心算法

/* 变量
  a尾: taila
  a头:taila.next
  b尾:tailb
  b头:tailb.next
*/
// 先将b尾指向a的头,需要定义p记录b尾原来的值
// 再将a的尾指向b的头
Node p = tailb.next;      //记录b尾的指向,也就是b头
tailb.next = taila.next;    //b尾指向a头
taila.next = p.next;      //a尾执行b头

5.双向链表


5.1定义

  • 一个结点由两个指针域,一个指针域指向前驱结点,另一个指针域指向后继结点,这种链表称为双向链表
  • 数据域 data
  • 前驱结点指针域:prior
  • 后继结点指针域:next微信图片_20220530204400.png

  5.2算法:插入


  • 需求:向结点p前面插入新结点s微信图片_20220530204457.png
/* 变量
  结点a:p.prior
*/
p.prior.next = s;   //结点a指向结点s
s.prior = p.prior;    // 结点s指向结点a
p.prior = s;      //结点p指向结点s
s.next = p;       //结点s执行结点p
//注意:必须先处理结点a,否则无法获得结点a

5.3算法:删除


  • 需求:删除p结点

微信图片_20220530204612.png

// a.next = b
p.prior.next = p.next;
// b.prior = a
p.next.prior = p.prior
相关文章
|
5月前
|
存储 C语言
数据结构中的线性表链式存储介绍及其基本操作
链式存储是线性表的一种重要存储方式,它通过节点和指针的结构,实现了灵活的动态存储管理。本文介绍了单向链表的基本操作,并提供了相应的C语言代码示例。理解和掌握链表的操作对学习和应用数据结构具有重要意义。希望这篇博客能帮助你更好地理解线性表的链式存储。
126 2
|
1月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
29 6
|
12天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之王道第2.3章节之线性表精题汇总二(5)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
IKU达人之数据结构与算法系列学习×单双链表精题详解、数据结构、C++、排序算法、java 、动态规划 你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
存储
【数据结构】线性表和顺序表
【数据结构】线性表和顺序表
21 1
|
5月前
|
算法
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
46 0
|
1月前
01(数据结构考研)线性表相关操作代码
01(数据结构考研)线性表相关操作代码
53 0
|
1月前
|
存储 C语言
数据结构之线性表的初始化及其操作
数据结构之线性表的初始化及其操作
33 0
|
2月前
|
存储 Java
java数据结构,线性表顺序存储(数组)的实现
文章介绍了Java中线性表顺序存储(数组)的实现。线性表是数据结构的一种,它使用数组来实现。文章详细描述了线性表的基本操作,如增加、查找、删除、修改元素,以及其他操作如遍历、清空、求长度等。同时,提供了完整的Java代码实现,包括MyList接口和MyLinearList实现类。通过main函数的测试代码,展示了如何使用这些方法操作线性表。
|
3月前
|
存储 算法 Java
"解锁Java对象数据结构的奥秘:从基础到实战,与热点技术共舞,让你的编程之路更激情四溢!"
【8月更文挑战第21天】Java以对象为核心,它是程序的基本单元与数据处理的基础。对象源自类,拥有属性(字段)和方法。对象在内存中分为对象头(含哈希码、GC信息等)和实例数据区(存储属性值)。例如,`Student`类定义了姓名、年龄等属性及相应的方法。通过`new`关键字实例化对象并调用其方法进行数据操作,是Java编程的关键技能。
30 0
|
5月前
|
存储 测试技术
【数据结构】操作受限的线性表,栈的具体实现
【数据结构】操作受限的线性表,栈的具体实现
59 5
下一篇
无影云桌面