目录
前情回顾
顺序表:数据存在一个连续的物理空间中
优势:
- 物理空间连续
- 下标的随机访问
劣势:
- 空间不够,需要扩容。扩容有一定性能消耗,其次一般扩容2倍,会存在一些空间浪费。
- 头部或者中间位置的插入删除效率低下(只有尾插尾删效率比较高)
有什么改善方式呢?
那我们就需要链表结构来进行改善。
1.链表
1.1 链表的概念及结构
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表
中的指针链接次序实现的 。
- 按需申请释放空间(链表可以将数据存放在单独空间中)
- 头部或者中间需要插入删除,不需要挪动数据
用一个指针指向第一个结点(头指针或头结点),依次往下指,遇见空指针截止
链表的是针对顺序表的劣势去设计出来的
示例一个链表的基本结构
SList.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDataType;
struct SListNode
{
SLDataType data;
struct SListNode* next;//指向下一个结点的指针
};
给了四个结点,如何链接?
SList.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDataType;
typedef struct SListNode
{
SLDataType data;
struct SListNode* next;//指向下一个结点的指针
}SLTNode;
Test.c
#include "SList.h"
//输入一些值,创建一个链表
void TestSList1()
{
SLTNode* n1 = malloc(sizeof(SLTNode));
assert(n1);
SLTNode* n2 = malloc(sizeof(SLTNode));
assert(n2);
SLTNode* n3 = malloc(sizeof(SLTNode));
assert(n3);
SLTNode* n4 = malloc(sizeof(SLTNode));
assert(n4);
n1->data = 1;
n2->data = 2;
n3->data = 3;
n4->data = 4;
n1->next = n2;
n2->next = n3;
n3->next = n4;
n4->next = NULL;
}
int main()
{
TestSList1();
return 0;
}
从图片上来看,逻辑结构:箭头只是形象的说法
代码写法:
n1->next = n2;
n2->next = n3;
n3->next = n4;
n4->next = NULL;
n1……n4是结构体指针,指针存的是地址,指向的是一个结构体的地址
结构体指针通过箭头访问到next
物理结构:在内存中的存储形式的体现
第一个结点存第二个结点的地址->第二个结点存第三个结点的地址->……->第四个存NULL的地址
1.2链表的实现
以下具体分析一些部分难点
1.2.1如何写打印
SList.c
#include "SList.h"
void SListPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while ( cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;//取指向结构体中的next的值 赋值行为
}
p