从0开始学算法5:线性表

一、什么是线性表

线性表的定义是描述其逻辑结构,而通常会在线性表上进行的查找、插入、删除等操作。

线性表作为一种基本的数据结构类型,在计算机存储器中的映象(或表示)一般有两种形式,一种是顺序映象,一种是链式映象。

二、线性表的顺序存储

1.定义

若将线性表L=(a0,a1, ……,an-1)中的各元素依次存储于计算机一片连续的存储空间,这种机制表示为线性表的顺序存储结构。

2.特点

  • 逻辑上相邻的元素 ai, ai+1,其存储位置也是相邻的;
  • 存储密度高,方便对数据的遍历查找。
  • 对表的插入和删除等运算的效率较差。

三、线性表的链式存储

1.定义

将线性表L=(a0,a1,……,an-1)中各元素分布在存储器的不同存储块,称为结点,每个结点(尾节点除外)中都持有一个指向下一个节点的引用,这样所得到的存储结构为链表结构。

在这里插入图片描述

2.特点

  • 逻辑上相邻的元素 ai, ai+1,其存储位置也不一定相邻;
  • 存储稀疏,不必开辟整块存储空间。
  • 对表的插入和删除等运算的效率较高。
  • 逻辑结构复杂,不利于遍历。

四、线性表、顺序表、链表之间区别和联系

线性表:逻辑结构, 就是对外暴露数据之间的关系,不关心底层如何实现。

顺序表、链表:物理结构,他是实际物理地址上的结构。比如顺序表就是用数组实现。而链表用指针完成主要工作。不同的结构在不同的场景有不同的区别。

比如:对于java来说,大家都知道List接口类型,这就是逻辑结构,因为他就是封装了一个线性关系的一系列方法和数据,而具体的实现其实就是跟物理结构相关的内容。比如顺序表的内容存储使用数组的,然后一个get,set,add方法都要基于数组来完成。而链表是基于指针的,当我们考虑对象中的数据关系就要考虑指针的属性,指针的指向和value。

对于一个线性表来说,不管它的具体实现方法如何,我们应该有的函数名称和实现效果应该一致。你也可以感觉的到在一些结构的设计,比如List的Arraylist和LinkedList、Map的HashMap和currentHashMap他们的接口api都是相同的,但是底层设计实现肯定是有区别的。

所以,基于面向对象的编程思维,我们可以将线性表写成一个接口,而具体实现的顺序表和链表可以继承这个接口的方法,提高程序的可读性。

五、顺序表

1.插入

add(int index,T t)

其中index为插入的编号位置,t为插入的数据

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

根据图片你就很好理解插入操作。当插入一个index时候,他的后面所有元素都要后移一位。你可以看的出插入时候整个操作的臃肿性。所以这也是顺序表性能表现最差的地方:频繁的插入,删除。

2.删除

同理,删除也是非常占用资源的。原理和插入类似,不过人走了,空一个小板凳后面的人需要往前挪。

在这里插入图片描述

3.其他操作

其他操作就很简单了。比如如果按照编号获取数据getElem(int index),你可以直接根据数据座标返回。a[index],而其他操作,可以通过遍历直接操作数组即可。

六、链表

1.指针

我想,表应该是很多人感觉很绕的东西,这个很大原因可能因为指针。很多人说java没指针,其实java他也有隐形指针。只不过不能直接用罢了。

指针建立的数据关系往往比数组这些要抽象的多。对于指针域,你把他当成一个对象就好了,不过这个对象指向的是另一个同等级对象。对于这个关系,你可以比作每个person类。每个person类都有老公(老婆),而这个老公老婆也是一个实际对象,可以理解这更像一种逻辑约定关系,而不是硬生生的关系吧。
在这里插入图片描述
指针你可以考虑成脑子记忆。上面的顺序表我们说它有序因为每个小板凳(数组)有编号,我们可以根据这个来确定位置。而对于链表来说,你可以看作成一个站在操场上的一队人。而他的操作也略有不同,下面针对一些比较特殊和重要的进行归纳。

2.基本结构

对于线性表,我们只需要一个data数组和length就能表示基本信息。而对于链表,我们需要一个node(head头节点),和length,当然,这个node也是一个结构体。

class node<T>{
    T data;//节点的结果
    node next;//下一个连接的节点
    public node(){}
    public node(T data)
    {
        this.data=data;
    }
    public node(T data, node next) {
        this.data = data;
        this.next = next;
    } 
}

当然,这个节点有数据域和指针域。数据域就是存放真实的数据,而指针域就是存放下一个node的指针。所以相比顺序表,如果用满数组情况下,链表占用更多的资源,因为它要存放指针占用资源。

在这里插入图片描述

3.链表操作

  • 插入
    add(int index,T t) 其中index为插入的编号位置,t为插入的数据 加入插入一个节点node,根据index找到插入的前一个节点叫pre。

    操作流程为:
    1.node.next=pre.next如下1的操作,将插入节点后面联系起来。此时node.next和pre.next一致。

    2.pre.next=node因为我们要插入node,而node链可以替代pre自身的next。那么直接将pre指向node。那么就相当于原始链表插入了一个node。

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章