数据结构(二)----线性表(List)链式存储结构(1)

4 篇文章 0 订阅
3 篇文章 0 订阅

相关概念

链式存储结构/链式表

定义

数据域:存储数据元素的信息
指针域:存储直接后继位置,指针域中存储的信息叫做指针或链
结点Node:数据域+指针域
所以一般Node类设计:

//java
class Node{
    int data; //数据域
    Node next; // 指针域

	Node(int val){
	    //	构造方法
		this.data = val;
		this.next = null;
	}
}
# python
class Node(Object){
	def __init__(self, val):
		self.data = val;
		self.next = None;
}

n个结点链成一个链表,即为线性表的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表
头指针:链表中第一个结点的存储位置
头结点:在单链表的第一个结点前附设一个结点(头结点数据域可以不存储任何信息,头
结点的指针域存储指向第⼀个结点的指针)
链表示意图

头指针头结点
头指针是指链表指向第⼀个结点的指针,若链表有头结点,则是指向头结点的指针为了⽅便操作⽽设⽴,放在第⼀元素的结点之前,数据域⼀般⽆意义(可存放链表⻓度)
头指针具有标识作⽤,通常⽤头指针作为链表的名字有头结点后对于第⼀元素结点的插⼊和删除与其他结点⽆异)
⽆论链表是否为空,头指针均不为空。头指针是链表的必要元素头结点⾮必需

链式存储特点

⽤⼀组任意的存储单元存储线性表的数据元素,存储单元可以是连续的也可以是不连续的,所以数据元素可以存在内存未被占⽤的任意存储位置

单链表

注:下文中提到的length为链表长度/链表有效元素个数

单链表读取

  1. 声明⼀个结点p指向链表第⼀个结点,初始化i从1开始;
  2. 当i<length时,遍历链表,让p指针向后移动不断指向下⼀结点,i++;
  3. 若到链表末尾p为空,则说明第i个元素不存在;
  4. 否则查找成功,返回结点p的数据。

单链表插入

  1. 声明⼀个结点p指向链表第⼀个结点,初始化i从1开始;
  2. 当i<length时遍历链表,p指针向后移动不断指向下⼀个结点,i++
  3. 当遍历到链表尾p为空,说明第i个元素不存在
  4. 否则查找成功,⽣成空结点s
  5. 将要插⼊的结点赋值给s→data
  6. 单链表的标准插⼊:
    s→next=p→next;
    p→next=s;

    (如果交换语句顺序:p→next=s;s→next=p→next; 会导致,
    p→next⾸先会被覆盖成s的地址,那么s→next=s,
    此时原本的p→next就没有了上级,链表造成断链)
  7. 返回成功

单链表删除

  1. 声明⼀个结点p指向链表的第⼀个结点位置,初始化i从1开始
  2. 当i<length时遍历链表,指针p后移,i++
  3. 当到链表尾部p尾空,说明第i个元素不存在
  4. 否则查找成功,将要删除的结点赋值为q,即p→next=q
  5. 删除p→next = q→next(其实4、5步综合来看就是p→next=p→next→next; 只是
    我们需要删除的结点data值,多了⼀个变量缓存它)
  6. 将q结点的data值赋值给e,等待返回
  7. 释放q结点(一般来说c c++就要手动释放,java和python有自动回收机制)
  8. 返回e

时间复杂度

遍历查找第i个元素+插入/删除元素,都为O(n)
情况:当从第i个位置 插⼊10个元素
顺序表:每次都要移动n-i个元素,每次都是O(n)
单链表:只需要第⼀个找到第i个位置的指针此时为O(n),接下来都是移动指针,时间复
杂度都为O(1)
总结:插⼊或删除越频繁,单链表优势会更⼤

单链表整表创建

  1. 声明⼀结点p和计数器变量i;
  2. 初始化空链表L
    头插法
    (3). 让L的头结点的指针指向NULL,建⽴⼀个带头结点的单链表
    (4). 循环p:
     a. ⽣成新的结点赋值给p;
     b. 随机⽣成数字赋值给p的数据域p→data
     c. 将p插⼊到头结点与前⼀新结点之间
    头插法
    尾插法
    (3). 新建r指向尾部结点 r=*L
    (4). 循环p:
     a. ⽣成新的结点p
     b. 随机⽣成数字赋值给p的数据域p→data
     c. 将表尾终端结点的指针指向新指针 r→next=p
     d. 将当前的新结点定义成表尾终端结点 r=p
    (5). 将最后链表的指针域置空,明晰尾部 r→next=NULL

单链表整表删除

  1. 声明结点p和q
  2. 将第⼀个结点赋值为p
  3. 循环p:
    a. 将下⼀结点赋值给q
    b. 释放p
    c. 将q赋值p
  4. 最后将头结点指针域置为空
    q的作⽤:记录下⼀结点,以便等当前结点释放后,把下⼀结点拿回来补充

顺序存储与链式存储差异

存储分配⽅式时间性能空间性能
顺序存储⽤⼀段连续的存储单元依次存储线性表的数据元素查找:顺序存储O(1) 单链表O(n)顺序存储需预分配存储空间,分⼤了,浪费,分⼩了容易发⽣上溢
单链表采⽤链式存储结构,⽤⼀组任意的存储单元存放元素插⼊删除:顺序存储结构需要平均移动表⻓⼀半的元素O(n)单链表找出某位置的指针后,插⼊和删除为O(1)单链表不需要分配存储空间,只要有就可以分配,元素个数不受限制

Python代码链接

本章节python相关代码链接
其中single_link_list.py 为顺序结构线性表
其他的文件可以看README.md里面有详解

Java代码链接

本章节python相关代码链接
其中SingleLinkList.java 为顺序结构线性表
其他的文件可以看README.md里面有详解

如果文章或者代码有问题,欢迎帮我指出,感激不尽,互勉~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值