数据结构与算法(二)-顺序表、单链表、单向循环链表

273 阅读3分钟

线性表

顺序表

  • 特点
  1. 顺序存储(逻辑相邻,物理存储地址相邻)
  2. 存在唯一一个”第一个元素“。
  3. 存在唯一一个”最后一个元素“。
  4. 前驱:除第一个外,每个数据元素都有一个。
  5. 后继:除最后一个外,每个数据元素都有一个。
  6. 无法反向查询
  7. 清除时:表->lenth = 0,无需其他操作,在创建时内存已固定,除非程序关闭才会消失。

单链表

  • 结点:包含数据域和指针域

单链表逻辑结构

  1. 头结点:便于插入和删除结点时做统一处理
  • 插入

单链表插入
注:4、5步顺序不能返,不然Hank结点会丢失

  • 删除

单链表删除
注:删除的结点需要free,不然会成为野指针。

  • 前插法

单链表前插法

  • 后插法

单链表后插法

单向循环链表

  • 链表结构与顺序存储结构优缺点对⽐比
  1. 存储分配⽅方式

    顺序存储结构⽤用⽤用⼀一段连续的存储单元依次存储线性表的数据元素; 单链表采⽤用链式存储结构,⽤用⼀一组任意的存储单元存放线性表的元素;

  2. 时间性能

    2.1 查找

    顺序存储 O(1)。
    单链表O(n)。
    

    2.2 插⼊入和删除

    存储结构需要平均移动⼀一个表⻓长⼀一半的元素,时间O(n) 。
    单链表查找某位置后的指针后,插⼊入和删除为 O(1)。
    

    2.3 空间性能

    顺序存储结构需要预先分配存储空间,分太⼤大,浪费空间;分⼩小了了,发⽣生上溢出。
    单链表不不需要分配存储空间,只要有就可以分配, 元素个数也不不受限制。
    
  • 初始化
  1. 第一次创建:结点指向自身
  2. 已创建,新增结点:找链表尾结点,将尾结点的next = 新结点. 新结点的next = 首元结点。(以尾插法为例)
  • 插入
  1. 当插入位置为0时:

    如果插入的位置为0,则属于插入首元结点,所以需要特殊处理
    创建新结点temp,并判断是否创建成功,成功则赋值,否则返回ERROR;
    找到链表最后的结点_尾结点,
    让新结点的next = 头结点.
    尾结点的next = 新的头结点;
    让头指针指向temp(临时的新结点)
    
  2. 当插入的位置在其他位置:

    创建新结点temp,并判断是否创建成功,成功则赋值,否则返回ERROR;
    先找到插入的位置,如果超过链表长度,则自动插入队尾;
    通过target找到要插入位置的前一个结点;
    新结点的next 指向target原来的next位置;
    target -> next 指向新结点;
    
  • 删除
  1. 当删除位置为0时:

    链表还有很多数据,但是删除的是首结点;
    记录原头结点
    找到尾结点;
    头指针指向头指针的next;
    使尾结点的next 指向新头结点 target->next = (*L);
    释放原来的头结点
    
    注:如果删除到只剩下首元结点了,则直接将*L置空;
    
  2. 当删除其他结点:

    记录要删除的结点;
    找到删除结点前一个结点target;
    使得target->next 指向 需要删除结点的next;
    释放需要删除的结点
    
  • 查询
int findValue(LinkList L,int value){
    int i = 1;
    LinkList p;
    p = L;
    //寻找链表中的结点 data == value
    while (p->data != value && p->next != L) {
        i++;
        p = p->next;
    }
    //当尾结点指向头结点就会直接跳出循环,所以要额外增加一次判断尾结点的data == value;
    if (p->next == L && p->data != value) {
        return  -1;
    }
    return i;
    
}