在存储结构上,不需要连续的存储空间,需要上一个结点的指针域 指向下一个结点即可,找到一个结点就可以找到下一个结点。

学习教材是大话数据结构,加上自己的一些个人理解。这个算法 有点绕,需要对指针 相关内容相当熟悉。通过学习感觉单链表相关算法还是蛮考验C知识的和逻辑思维。

下面看代码:

#include <stdio.h>
#include <stdlib.h>
#define ERROR 0
#define OK 1
typedef int EleType;
typedef int Status;
typedef struct Node Node;//链表元素
struct Node
{EleType data;//数据域Node * next;//指针域
};
typedef Node* LinkList;
void printLinkList(const LinkList * const list) {if (NULL ==list) {//链表为空printf("printLinkList error \n");return;}int i = 1;LinkList li = (*list)->next;//从头结点后面第一个结点开始遍历while (li)//最后一个元素没有指向,不会进行循环。{printf("第%d元素:%d\t", i, li->data);li = li->next;i++;}printf("\n");return;
}
//创建拥有头结点的链表
//头插法创建链表,往链表中添加元素,新创建的的元素始终在头结点后面类似 头指针 -> 头结点->An->An-1->An-2 ...-> A1
//元素的数据 随机生成100以内的数字
Status creatLinkListInHead(LinkList *list,int n) {srand(time(0));//设置随机种子,为产生随机数做准备。//LinkList 类型 和 Node * 类型是一样的!看最上方定义类型别名,为什么可以做呢?链表的头指针 就是指向结点Node,所有链表类型是 Node *,只是为了更好看而已。 LinkList li=NULL;Node *node=NULL;//可以定义为 LinkList *node = NULL;int i = 0;li = (LinkList)malloc(sizeof(Node));//头指针指向头结点,给头结点分配空间if (NULL == li||n<0) {//分配内存空间失败或者链表元素个数非法 返回return ERROR;}li->next = NULL;//初始头结点没有指向for ( i = 0; i < n; i++){node = (Node*)malloc(sizeof(Node));//给结点分配空间if (NULL==node) {//给分配空间失败 return ERROR;}node->data = rand()%100;//除以100取余的到100以内的数字,不包括100,如果含100 就需要+1node->next = li->next;//新添加的元素指针域 指向头结点后面的结点li->next = node;//头结点指针域 指向新增加的元素}*list = li;//通过指针 给外部链表赋值return OK;
}
//尾插法创建链表,往链表中添加元素,先添加的元素放前面,后添加的元素放后面,遵循先来后到的道理
Status creatLinkListInTail(LinkList *list, int n) {srand(time(0));//设置随机种子LinkList li = NULL ;Node *node = NULL;int i = 0;li = (LinkList)malloc(sizeof(Node));if (NULL == li || n<0) {//分配内存空间失败或元素个数非法return ERROR;}li->next = NULL;//初始头结点指向*list = li;//给通过外部链表赋值,指向头结点,此时 list 和 li 都指向头结点。for ( i = 0; i < n; i++){node = (Node*)malloc(sizeof(Node));//给结点分配空间if (NULL == node) {//分配空间失败 return ERROR;}node->data = rand() % 100;//除以100取余的到100以内的数字,不包括100,如果含100 就需要+1li->next = node;//新结点 放到链表末尾li = node;//移动链表指针指向最新链表最后一个元素,为了下次循环在链表末尾添加元素//temp = node;}//最后表尾元素指针域 设置NULLli->next = NULL;//*list = li;//一定要放在for循环前面,不然头结点的内存空间没有指向!起初l指向头结点,但是进入for循环后l的指向发生改变要移动指向最新添加的结点元素。return OK;
}
//获取链表元素数据,通过指针返回 链表第i个元素的 数据
//i还是按国人的顺序来吧,从1开始
Status getELement(LinkList list, int position,EleType *e) {//异常情况:空指针,元素位置非法if (NULL == list || position < 1) {return ERROR;}LinkList li = list;int i = 1;while (li && i<position) {//在链表范围内遍历元素 直到 找到第position位置的 元素  i++;li = li->next;}if (NULL == li || position > i) {//超出链表范围,都遍历完链表还没找到元素。return ERROR;}//通上面 while循环 当i = position 跳出循环 ,li 此时指向链表 第position位置的 前面一个结点。*e = li->next->data;return OK;
}
//往链表中第position位置 插入元素,元素数据为 e
//元素位置从1开始数
Status insertLinkList(LinkList *list,int position,EleType e) {Node *node = (Node*)malloc(sizeof(Node));//异常情况:空指针,为插入元素分配空间失败,元素位置非法,if (NULL == list || NULL==node || position < 1) {return ERROR;}LinkList li = * list;int i = 1;while ( li && i<position) {//在链表范围内遍历元素 直到 找到第position位置的 元素  i++;li = li->next;}if (NULL == li || position > i) {//超出链表范围return ERROR;}//通上面 while循环 当i = position 跳出循环 ,li 此时指向链表 第position位置的 前面一个结点。node->data = e;node->next = li->next;//让 插入结点指针域指向 原来位置的结点li->next = node;//让插入结点位置前的结点 指向插入结点return OK;
}
//在链表第position位置 删除元素,通过指针返回 删除元素的数据内容
Status delLinkListEle(LinkList *list, int position, EleType *e) {//异常情况:空指针,元素位置非法if (NULL == list || position < 1) {return ERROR;}LinkList li = *list;Node * node = NULL;int i = 1;while (li && i<position) {//在链表范围内遍历元素 直到 找到第position位置的 元素  i++;li = li->next;}if (NULL == li || position > i) {//超出链表范围,都遍历完链表还没找到元素。return ERROR;}//通上面 while循环 当i = position 跳出循环 ,li 此时指向链表 第position位置的 前面一个结点。node = li->next;//保存要删除元素的地址li->next = node->next;//让删除元素前置结点 指向 删除元素 直接后继结点。然后就可以释放 删除结点的空间了。*e = node->data;//将删除元素数据通过指针修改返回free(node);//释放删除元素空间return OK;
}
//清空整个链表,释放指针指向的内存
Status freeLinkList(LinkList *list) {if (NULL == list)//空指针return ERROR;//注意:头结点不要释放!只释放头结点后面的结点元素//LinkList li = *list;这样将会把头结点也释放掉LinkList li = (*list)->next;//将链表指针指向第一个结点元素,从这个元素开始释放Node * node = NULL;//临时变量,指向还未释放的元素while (li){//链表指针向移动指向结点元素,直到没有后继结点node = li->next;//保存要释放结点 的直接后继结点位置。 free(li);li = node;//继续指向 未释放结点}//将头结点指针域设置为NULL(*list)->next = NULL;return OK;
}
int main(void) {LinkList linkList;EleType e;printf("头插法创建链表结构:\n");creatLinkListInHead(&linkList, 4);printLinkList(&linkList);//先释放 然后再用尾插法freeLinkList(&linkList);printf("尾插法创建链表结构:\n");creatLinkListInTail(&linkList, 4);printLinkList(&linkList);printf("第%d个位置插入%d:\n",5,100);//插入元素insertLinkList(&linkList, 5, 100);//往链表尾结点后面插入元素printLinkList(&linkList);printf("第%d个位置插入%d:\n", 3, 103);//插入元素insertLinkList(&linkList, 3, 103);//链表中间插入元素printLinkList(&linkList);//获取元素getELement(linkList, 4, &e);printf("第%d个位置元素:%d\n", 4,e);//删除元素delLinkListEle(&linkList, 5, &e);printf("第%d个位置删除:%d\n", 5, e);printLinkList(&linkList);//删除元素delLinkListEle(&linkList, 1, &e);printf("第%d个位置删除:%d\n", 1,e);printLinkList(&linkList);//释放整个表freeLinkList(&linkList);system("pause");return 0;
}

结果验证截图:

线性表之链式存储结构_单链表相关算法相关推荐

  1. php数据结构链表代码,数据结构之线性表——链式存储结构之单链表(php代码实现)...

    /** * * 1. 类LNode用作创建单链表时,生成新的节点. * 2. 类SingleLinkList用于创建单链表以及对单链表的一些操作方法(实例化此类就相当于创建了一个空链表) * 3. C ...

  2. 数据结构之线性表——链式存储结构之单链表(php代码实现)

    <?php /**** 1. 类LNode用作创建单链表时,生成新的节点.* 2. 类SingleLinkList用于创建单链表以及对单链表的一些操作方法(实例化此类就相当于创建了一个空链表)* ...

  3. 数据结构——线性表之链式存储结构

    单链表: 概念: 1.由于线性表的顺序存储在插入与删除时需要移动大量元素,适用于不经常改变元素的情况,那么当我们需要经常操作元素时该怎么办,这就有了接下来的线性表的链式存储结构 2.单链表在内存的存储 ...

  4. 线性表之链式存储结构

    线性表的顺序存储结构,插入和删除时需要移动大量元素,耗费时间,可解决这些问题. 转载于:https://www.cnblogs.com/cailingsunny/p/4562287.html

  5. 线性表-链式存储结构

    3.6 线性表的链式存储结构 3.6.1 顺序存储结构不足的解决办法 前面我们讲的线性表的顺序存储结构.它是有缺点的,最大的缺点就是插入和删除时需要移动大量元素,这显然就需要耗费时间.能不能想办法解决 ...

  6. python 单链表节点怎么快速定义_线性表链式存储结构之单链表

    线性表的链式存储结构的特点就是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以在内存中未被占用的任意位置.比起顺序存储结构每个元素只需要存储一个位置就可以了.现在链式存储结构中,除了要存储数 ...

  7. 线性表的链式存储结构以及单链表的插入和删除原理实现

    线性表的链式存储结构 线性表中的每个元素最多只有一个前驱元素和一个后继元素(其逻辑结构),因此可以采用链式存储结构存储. 链表 线性表的链式存储结构称为链表.在链表中每个结点不仅包含有元素本身的信息( ...

  8. 数据结构与算法(2-2)线性表之链式存储(单链表、静态链表、循环链表、双向循环链表)

    目录 一.单链表 1.存储方式 2.插入 3.删除 总代码: 二.静态链表 1.存储方式 2.插入 3.删除 4.遍历 总代码: 三.循环链表 总代码: 四.双向循环链表 1.存储方式: 2.插入和删 ...

  9. 数据结构-- 线性表之链式存储

    https://www.cnblogs.com/ZWOLF/p/10604252.html

最新文章

  1. 使用镜像加速 Rtools 下载与安装
  2. 086_访问html元素
  3. 钢琴演奏:舒伯特的小夜曲 --- 女儿的钢琴学习
  4. 【客户下单】后台系统自动分单成功生成工单发送短信
  5. 汇编语言--微机CPU的指令系统(五)(字符串操作指令)
  6. 【转】shell之for、while、until循环
  7. Python之NumPy(axis=0 与axis=1)区分
  8. python文件处理seek()方法的参数是_Python 文件(File) seek() 方法
  9. 设计模式(二) 模板方法
  10. 关于大学老师,我们常有的6种误解!
  11. 简单技能之程序调试入门
  12. TeamViewer——Ubuntu系统上的安装和卸载
  13. hypermesh 错误 2005
  14. Idea安装MarkDown插件
  15. Python读取本地html文件,获取其中表格内容
  16. 24点游戏 java实现,一个基于Java技术编写的24点游戏逼真图形版,调用了很多图片去显示游戏内容JAVA游戏源码下载...
  17. OLAP 系统选型,选 Apache Kylin 还是 ClickHouse?
  18. win10语言包在c盘哪里,win10系统通过卸载语言包释放c盘空间的操作方法
  19. 【转】我公务员工作七年后的肺腑之言
  20. AS608指纹模块开发教程

热门文章

  1. 「M1兼容」最新ps2022版photoshop 2022 Mac中文版下载安装教程分享
  2. 轻松使用终端开启macOS系统的隐藏功能,小白都能看得懂
  3. python计算选手最后得分并取出前三名_MySQL中查询获取每个班级成绩前三名的学生信息...
  4. 入门级图论算法:洪水填充算法
  5. 1.5 编程基础之循环控制 09 奇数求和
  6. 游戏开发使用的各个主流引擎对比
  7. STM32F407+CubeMX-使用TIM产生PWM信号
  8. 记忆化搜索斐波那契c语言,记忆化搜索--优化斐波那契数列递归函数
  9. 数仓dw怎么建_从0建设离线数据仓库
  10. vue中rules校验是验证首字符_小白也能秒懂Vue源码中那些精细设计(选项处理)...