☰
数据结构笔记一 : 数据结构入门 · 链表
2026/10/14 2:53:33 网站建设 项目流程

一、什么是数据结构

1. 定义

数据结构 = 研究 数据 与 数据之间的关系。

数据处理规模的递进:

1.C语言语法2.基本编程思维3.处理单个或几个变量的数据4.处理批量数据(数组+结构体)5.数据规模更大->研究 数据与数据之间的关系(数据结构)->结合处理数据的思路(算法)->最终实现好的编程效果

一句话:数据结构就是研究"数据元素"与"数据元素"之间的关系。

2. 怎么学习

  • 数据结构的特点:抽象
    • 数据的操作(指针)
    • 代码实现?
  • 学习建议:画图(让抽象关系清晰明了)

3. 优秀程序员的基本功

一门编程语言+数据结构和算法(好的)程序设计=算法(好)+数据结构(合适的)

二、数据结构的内容与术语

术语含义
数据描述客观事物的符号
数据元素组成数据的、有一定意义的基本单位
数据项一个数据元素由若干个数据项组成(数据项是数据不可分割的最小单位)
数据对象性质相同的数据元素的集合,是数据的子集
数据结构相互之间存在一种或多种特定关系的数据元素的集合

例:单个学生 = 数据元素(一个有意义的基本单位);学生这种类型 = 数据对象。

三、数据的逻辑结构(数据之间的关系)

结构关系说明 / 例子
集合元素间同属一类(无对应)无关系
线性一对一的0-1-2-3,除首尾元素外,每个元素都有前驱节点和后继节点
树形一对多(层次)班主任 -> 班长 -> 副班 / 学委 / 纪委 / 劳委
图形多对多地图、抢票软件

四、数据的存储结构

数据最终还得存储到计算机中,怎么把具有逻辑关系的数据存储到计算机?

存储结构说明
顺序存储数组
链式存储链表(链 = 铁链、狗链)
索引结构index(目录/索引),专门维护一个索引表
散列(哈希)结构哈希查找:哈希表,值 <–哈希函数–> 位置

顺序存储(数组)优缺点

优点:随机访问方便 缺点:增、删(麻烦)

链式存储(链表)优缺点

优点:增、删除(方便) 缺点:访问需要遍历

顺序存储的增删(数组)

intsno[10]={0,1,2,3,4,5,6,7,8,9};// 增加一个学号 -> 思路:// 1. 新创建一个多一个元素的数组// 2. 将原数组数据拷贝过来,再新加一个数值// 3. 释放原有空间intsno1[11]={0,1,2,3,4,5,6,7,8,9,10};// 删除一个学号intsno1[10]={0,1,2,3,4,5,6,7,8,9};

同一逻辑关系的数据可以用不同存储结构存储,但不同存储结构对应处理思路(算法)也不同。用什么样的算法,取决于处理怎样关系(逻辑 + 存储)的数据。

五、数据结构知识体系

数据结构 ├── 逻辑结构(逻辑模型) │ ├── 集合结构 │ ├── 线性结构 │ ├── 树形结构 │ └── 图状结构 ├── 存储结构(映像到内存) │ ├── 顺序结构 │ ├── 链式结构 │ ├── 索引结构 │ └── 散列结构 └── 抽象数据类型(数据对象 + 数据关系 + 基本操作)

六、算法

定义:算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作。算法就是解决问题的步骤(是解决问题思路的具体描述)。

算法五大基本特性

1.输入2.输出3.有穷性4.确定性5.可行性

好算法的评判标准

1.正确性2.可读性3.健壮性(鲁棒性)4.时间效率和存储量低(时间复杂度 和 空间复杂度)

七、线性表(顺序表)

线性表是一对一的数据结构,顺序存储:C语言、C++、Java、Python 都支持。

数组(顺序表)的算法:创建、增、删、改、查、销毁。

// 1.创建inta[10];int*p=malloc(sizeof(int)*10);// 2.增inputArray();// 输入数据insertArray();// 插入数据// 3.删deleteArray();// 4.改modifyArray();// 找到 修改// 5.查findArray();// 6.销毁(堆区)free(p);// 数据销毁 / 空间销毁

八、链表(用链式方式实现线性结构)

1. 节点(结点)结构

节点包含:a. 数据 b. 下一个节点的地址

typedefintdata_t;structnode{data_tdata;// 数据域structnode*next;// 指针域:下一个节点的地址};typedefstructnodenode_t;

2. 带头链表

数据结构中 ——带头链表:

头节点->首节点->...->尾节点 数据域xxx 数据域1数据域3指针域 指针域 指针域NULL
  • 头节点:带头,数据域不关心
  • 首节点:第一个有效数据节点
  • 尾节点:最后一个有效数据节点(特点:指针域为 NULL)
  • 空链表:只有头节点,而且头节点的指针域为 NULL

3. 创建链表(创建空链表)

node_t*linklist_create(void){// 创建一个节点,充当头节点node_t*head=malloc(sizeof(node_t));// 头节点数据域不关心,指针域为 NULLhead->next=NULL;returnhead;// 返回头节点的地址}

4. 头插法(每次插入到头节点的后面)

voidlinklist_insert_head(node_t*phead,data_tdata){// 1.创建新节点node_t*pNew=malloc(sizeof(node_t));// 2.把 data 放到数据域中pNew->data=data;// 3.连起来pNew->next=phead->next;// (1) 新节点指向原首节点phead->next=pNew;// (2) 头节点指向新节点return;}

5. 判断链表是否为空

intis_empty(node_t*phead){// 空链表:只有头节点,phead->next == NULLreturnphead->next==NULL;}

6. 遍历打印

voidlinklist_print(node_t*phead){// 有效性验证:// 1. phead 有可能传的是 NULL// 2. 空链表:phead->next == NULLnode_t*p=phead->next;while(p!=NULL){printf("%d ",p->data);// 打印此时 p 所在节点的数据域p=p->next;// 向后移动}putchar('\n');}

7. 尾插法(每次插入到尾节点的后面)

voidlinklist_insert_tail(node_t*phead,data_tdata){// 1.创建新节点node_t*pNew=malloc(sizeof(node_t));// 2.把 data 放到数据域中pNew->data=data;pNew->next=NULL;// 3.连起来// a.先找到尾节点node_t*p=phead;while(p->next!=NULL){p=p->next;}// 写法1p->next=pNew;// 写法2(等价)// pNew->next = p->next;// p->next = pNew;return;}

8. 查找(按 key 找节点,返回节点地址)

node_t*linklist_find_key(node_t*phead,data_tkey){node_t*p=phead->next;while(p!=NULL){if(p->data==key){returnp;// 找到,返回节点地址}p=p->next;}returnNULL;}

9. 修改(找到位置上修改)

node_t*linklist_update(node_t*phead,data_told,data_tnew){node_t*p=linklist_find_key(phead,old);if(p!=NULL){p->data=new;// 找到位置上修改}returnp;// 返回节点地址}

10. 头删(砍头法:每次删除首节点)

intlinklist_delete_head(node_t*phead){// 1.删除:让头节点的指针域指向首节点的下个节点node_t*p=phead->next;phead->next=p->next;// 2.释放 p 指向的节点(原先的首节点)free(p);p=NULL;return0;}

11. 尾删(每次删除尾节点)

intlinklist_delete_tail(node_t*phead){// 思路:单向链表// 让 p 停在尾节点的前一个节点node_t*p=phead;while(p->next->next!=NULL)// 找到尾节点的前一个节点{p=p->next;}free(p->next);// 释放尾节点p->next=NULL;// p 所在节点成为新的尾节点return0;}

注:笔记中尾删循环条件while(p->next == NULL)是笔误,正确应为while(p->next->next != NULL)(让 p 停在尾节点的前一个节点),上面已按正确写法整理。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询