链表是线性结构的离散存储方式。

定义:n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,每个节点只有一个后续节点,首节点没有前驱节点,尾节点没有后续节点。

郝斌

专业术语

  1. 首节点(第一个有效节点,首节点的数据类型和头节点是一样的)

  2. 尾节点(最后一个有效节点)

  3. 头节点(在首节点之前,不存储有效数据、目的是为了方便对链表进行操作)、

  4. 头指针(指向头节点的指针变量)

  5. 尾指针(指向尾节点的指针变量)

只需要一个参数,头指针,通过头指针可以推算出链表的所有信息,就可以通过这一个参数使用函数对链表进行操作。

链表的优缺点:

优点:空间没有限制;插入删除元素很快。

缺点:存取速度很慢。

链表节点定义的方式,链表结构体中包含的指针域类型和节点类型相同,指向一个链表节点的整体。

typedef struct Node
{int data;struct Node *pNext;
}NODE, *PNODE;//为了统一链表的操作,我们可以这样定义链表
typedef struct Data
{char num[8];char name[8];int score;
}ElemType;typedef struct Node
{ElemType data;struct Node *pNode;
}Node, *pNode;

分类:

单链表,双链表(每一个节点有两个指针域)

循环链表(能通过任何一个节点找到其他所有的节点),非循环链表

下面进行算法实现:遍历,查找,清空,销毁,求长度,排序,删除节点,插入节点。

p->pNext 表示p所指向结构体变量中的pNext成员变量。

/*在指针p指向的链表节点后面插入指针q指向的链表节点的两种方式*/
//方法1r = p -> pNext;p -> pNext = q;q -> pNext = r;
//方法2q -> pNext = p -> pNext;p -> pNext = q;

删除指针p指向的链表节点之后的下一个链表节点,也就是把指针p指向的链表节点中的指针域指向下下一个节点,但是注意删除的节点要及时释放,否则会导致内存泄漏,C语言不会自动释放。。

//错误的写法p -> pNext = p -> pNext -> pNext;
//错误的写法,释放了p指针指向的链表节点的下一个节点之后,下下一个节点同样找不到了。free(p->pNext);
//正确的写法,先将需要释放的节点保存一下,删除操作之后再释放。r = p->pNext;p -> pNext = r->pNext;free (r);

我们对单链表进行相应功能函数的实现:

#include<stdio.h>
#include<malloc.h>
#include<stdbool.h>typedef struct Node
{int data;struct Node * pNext;
}NODE, *PNODE;PNODE create_list(void);
void show_list(PNODE phead);
bool is_emptylist(PNODE phead);
int length_list(PNODE phead);//节点个数统计
bool append_list(PNODE phead, int val);//追加
bool insert_list(PNODE phead, int val, int port);//插入
bool delete_list(PNODE phead, int* returnVal, int port);
void sort_list(PNODE phead, bool mode);int main(void)
{PNODE pNode = NULL;int lengNum = 0;
//    int returnNum =0;
/*关于指针的使用,直接初始化一个int值而不是int *去接受被删除的值 。*/pNode = create_list();show_list(pNode);if( is_emptylist(pNode) ){printf("链表为空!\n");}else{printf("链表不为空!\n");lengNum = length_list(pNode);printf("the Number of the link is %d \n", lengNum);}
/*if(insert_list(pNode, 88, 3)){printf("插入成功!\n");}else{printf("插入失败!\n");}*///delete_list(pNode, &returnNum, 3);sort_list(pNode, 0);show_list (pNode);sort_list(pNode, 1);show_list (pNode);//printf("the delete number is %d \n", returnNum);//    append_list(pNode, 7);return 0;
}PNODE create_list(void)
{int nodeNum = 0;int fornum = 0;int val = 0;/*   pNew 每次循环分配空间作为新的链表节点*//*   pTail 一直指向链表的最后一个节点,初始化时pTail的指针域赋NULL*/PNODE phead = (PNODE)malloc(sizeof(NODE));if(phead == NULL){printf("链表头申请失败! \n");return 0;}PNODE pTail = phead;pTail ->pNext = NULL;printf("please enter the number of Node: ");scanf(" %d", &nodeNum);for(fornum = 1; fornum <= nodeNum; fornum++){printf("please enter the data of this node %d :", fornum);scanf(" %d", &val);PNODE pNew = (PNODE)malloc(sizeof(NODE));if(pNew == NULL){printf("新链表节点申请失败! \n");return 0;}pTail ->pNext = pNew;pNew ->data = val;pNew ->pNext = NULL;pTail = pNew;}return phead;
}void show_list(PNODE phead)
{PNODE pShow = phead ->pNext;int nodenum = 1;while(pShow != NULL){printf("The data of Node %d is: %d \n", nodenum, pShow->data);pShow = pShow ->pNext;nodenum ++;}printf("\n");
}bool is_emptylist(PNODE phead)
{PNODE pShow = phead ->pNext;if(pShow == NULL){return true;}else{return false;}
}int length_list(PNODE phead)
{PNODE pShow = phead ->pNext;int lengthNum = 0;while(pShow != NULL){lengthNum ++;pShow= pShow->pNext;}return lengthNum;
}bool insert_list(PNODE phead, int val, int port)
{/*插入操作要考虑插入到第一个节点之前的情况,一开始要指向头节点*/PNODE pShow = phead;#if 0int nodeNum = 0;int i = 0;if(is_emptylist(phead)){printf("链表为空!\n");return false;}nodeNum = length_list(phead);if(nodeNum < port-1){printf("参数错误!\n");return false;}while(i < port-1 ){pShow = pShow->pNext;i ++;}PNODE pNew = (PNODE)malloc(sizeof(NODE));pNew ->pNext = pShow ->pNext;pShow ->pNext = pNew;pNew ->data = val;#endif // 0#if 1/*******郝斌版本*这种方式是不需要判断列表为空,也不需要求出列表长度******/PNODE pSwap = NULL;PNODE pNew = (PNODE)malloc(sizeof(NODE));int j = 0;while ((pShow != NULL) && (j < port -1)){pShow = pShow->pNext;j++;}if(j > port -1|| pShow==NULL){return false;}pSwap = pShow ->pNext;pShow ->pNext = pNew;pNew -> pNext = pSwap;pNew ->data = val;#endif // 1return true;
}bool append_list(PNODE phead, int val)
{PNODE pShow = phead;PNODE pTail = NULL;PNODE pNew = (PNODE)malloc(sizeof(NODE));if (pNew == NULL){printf("append_list 新节点申请失败!\n");return false;}while (pShow != NULL){pTail = pShow;pShow = pShow ->pNext;}pTail ->pNext = pNew;pNew->data = val;pNew->pNext = NULL;return true;
}bool delete_list(PNODE phead, int *returnVal, int port)
{PNODE pShow = phead ->pNext;int fornum = 1;PNODE pDeleteNode = NULL;while( (pShow != NULL) &&(fornum < port-1 ) ){pShow = pShow->pNext;fornum ++;}if ((fornum > port - 1) || (pShow->pNext == NULL)) /*将指针指向将要删除的节点的前一个节点,判断目标节点pShow->pNext是不是空节点*/{return false;}pDeleteNode = pShow->pNext;*returnVal = pDeleteNode ->data;pShow ->pNext = pDeleteNode ->pNext;free(pDeleteNode);pDeleteNode = NULL;return true;}
void sort_list(PNODE phead, bool mode)
{int nodeNum = length_list(phead);int i = 0;int j = 0;int swapNum = 0;PNODE pnode = NULL;PNODE qnode = NULL;if(mode == 0)/* 从小到大排列 */{for(i = 0, pnode = phead ->pNext; i < nodeNum - 1; i++, pnode = pnode ->pNext){for(j = i + 1, qnode = pnode ->pNext; j < nodeNum; j++, qnode = qnode ->pNext){if((pnode->data) > (qnode ->data)){swapNum = pnode->data;pnode ->data = qnode ->data;qnode ->data = swapNum;}}}}else if(mode == 1) /*从大到小排列*/{for(i = 0, pnode = phead ->pNext; i < nodeNum - 1; i++, pnode = pnode ->pNext){for(j = i + 1, qnode = pnode ->pNext; j < nodeNum; j++, qnode = qnode ->pNext){if((pnode->data) < (qnode ->data)){swapNum = pnode->data;pnode ->data = qnode ->data;qnode ->data = swapNum;}}}}return;
}

注意排序函数中使用了逗号运算符,其作用是将若干表达式连接起来。它的优先级是所有运算符中最低的,结合方向是自左至右。 逗号表达式: 一般形式:表达式1,表达式2,表达式3,......表达式n ​ 求解过程:先计算表达式1的值,再计算表达式2的值,......一直计算到表达式n的值。最后整个表达式的值是表达式n的值。

在for循环中使用逗号表达式注意第二个条件,循环执行判断条件中慎用逗号运算符,表达式顺序的不同会导致不同的判定结果。

王卓

[郝斌/王卓]数据结构C语句—链表相关推荐

  1. 【郝斌老师数据结构学习笔记 day 6】

    目录 前言 一.算法 二.几种常见存储结构浅析 三.非循环单链表算法演示合集 总结 前言 数据结构的学习笔记,记录第六天 一.算法 算法: 狭义:算法和数据的存储方式密切相关 广义:算法和数据的存储方 ...

  2. 【郝斌老师数据结构学习笔记 day 7】

    目录 前言 一.栈的定义 二.栈的分类 三.栈的一些算法 四.栈的日常应用 总结 前言 数据结构的学习笔记,记录第七天 一.栈的定义 定义:一种可以实现 "先进后出" 的存储结构 ...

  3. 【郝斌老师数据结构学习笔记 day 3】

    目录 前言 一.连续存储数组的算法演示 二.typedef 的用法 总结 前言 数据结构的学习笔记,记录第三天 一.连续存储数组的算法演示 线性结构[把所有的结点用一根直线穿起来] 连续存储[数组] ...

  4. 赫斌老师数据结构视频查缺补漏笔记

    赫斌老师数据结构视频查缺补漏笔记 观看学习赫斌老师数据结构的视频,记录下自己之前学习这块内容时似懂非懂的知识,仅针对自己查缺补漏使用 视频链接:<郝斌老师数据结构自学视频> 1.指针的大小 ...

  5. 郝斌数据结构——链表

    郝斌数据结构 -- 链表 文章目录 1. 定义 2. 专业术语: 3. 注意事项 4. 代码 1. 定义 定义:n 个节点离散分配:彼此通过指针相连:每个节点只有一个后续节点,首节点没有前驱 节点,尾 ...

  6. 郝斌数据结构教程 送给数据结构新手的福利

    下面的链接是郝斌数据结构教学视频下载地址: *无论在校大学生还是工作人员,数据结构是算法的奠基石,打好基础,至关重要. 各位在学习之余有空看看该教程会有很大的帮助,希望大家喜欢,多多支持. http: ...

  7. 郝斌数据结构全套教程高清在线观看和下载-学习数据结构必看

    郝斌数据结构全套共78集 郝斌数据高清在线观看 https://www.bilibili.com/video/av49304765/ 郝斌数据高清在线观看 https://www.bilibili.c ...

  8. 郝斌c语言大纲百度云,C语言学习大纲 郝斌(讲解)

    教你如何快速掌握C语言,郝斌讲解,幽默而且加深了解.... 语言概述: 1.为什么学习C语言 1). C的起源和发展 2).C的特点 优点 代码量小 速度快 功能强大 缺点 危险性高 开发周期长 可移 ...

  9. 青岛大学-王卓 数据结构与算法基础

    青岛大学-王卓 数据结构与算法基础 内容目录 文章目录 青岛大学-王卓 数据结构与算法基础 内容目录 第一周 1.0前言 1.1数据结构的研究内容 1.2基本概念和术语1 逻辑结构的种类 存储结构的种 ...

  10. C语言郝斌视频学习一 变量为什么要初始化和一个小例子以及大纲笔记

    在给变量分配内存时,很可能这段内存存在以前其他程序使用留下的值.当使用VC编译器,若编译器发现没有给变量赋值而使用,就会返回一个以"85"开头的很大的数字(此时该段内存中为一个垃圾 ...

最新文章

  1. 为什么一定要前后端分离?
  2. 面试官:说说操作系统微内核和Dubbo微内核?
  3. UDT协议实现分析——连接的建立
  4. 被替换的项目不是替换值长度的倍数_如果要在Excel中计算单元格内指定的字符长度,我推荐这两个公式.........
  5. Centos7 使用Docker MySQL部署_01
  6. iOS block 用法
  7. ai人工智能_AI如何帮助截肢者?
  8. 从零玩转第三方登录之QQ登录
  9. (12) 基于深度时空残差网络ResNet的城市交通流预测
  10. linux下Umail服务的停止
  11. p20 021 函数:我的地盘听我的
  12. 推荐2个开源聊天服务器
  13. 获取java可用时区列表ZoneId
  14. 分布式基础-分布式事务
  15. Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器,强烈推荐!
  16. 项目成本管理:项目成本控制
  17. win10耳机有杂音滋滋_蓝牙耳机的底噪和电流声有区别吗?双11五款高续航平价蓝牙耳机分享...
  18. Java之字符类型char
  19. 美国威士忌的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  20. 软件定义存储2.0,谁领风骚?

热门文章

  1. 支付宝当面付扫码支付支付后不回调_【支付宝支付】支付宝手机网站支付流程...
  2. 《Qt 5/PyQt 5实战指南》目录
  3. javascript获取浏览器窗口大小 获取屏幕,浏览器,网页高度宽度
  4. JavaScript 动态生成表格 案例
  5. ajax中GET和POST区别
  6. samba服务设置与访问共享文件夹
  7. vue 自定义打印CLodop
  8. 支持lodop的服务器,clodop云打印服务器未响应(lodop打印)
  9. 《Renewable Energy》论文格式
  10. 有关计算机专业工作室的名字,盘点最好听的工作室名字大全