【数据结构学习1】数据结构基本概念及单向链表

发布时间:2026/8/13 20:46:10
【数据结构学习1】数据结构基本概念及单向链表 文章目录数据结构一、数据结构的基本概念二、数据结构数据与数据之间的关系2.1 逻辑结构2.2 物理结构2.3 数据结构主要学习内容2.4 知识储备三、单向链表3.1 创建链表3.2 链表插入3.3 链表删除3.4 链表查找3.5 链表修改3.6 链表遍历3.7 链表销毁数据结构一、数据结构的基本概念数据定义数据是描述客观事物的符号是计算机中可以操作的对象是能被计算机识别并输入给计算机处理的符号集合。注数据其实就是符号其必须具备两个条件可以输入到计算机中。能被计算机处理。数据元素是组成数据的、有一定意义的基本单位在计算机中通常作为整体处理也被称为记录。例如禽类的数据元素就有牛、马、羊等等。数据项一个数据元素可以由若干项数据项组成。数据项是数据不可分割的最小单位。数据对象是性质相同的数据元素的集合是数据的子集数据结构存储具有一种或多种特定关系的数据的集合如何存储数据。二、数据结构数据与数据之间的关系2.1 逻辑结构数据元素与元素之间的关系集合数据元素与元素之间关系平等即集合结构中的数据元素除了同属于一个集合外它们之间没有其他关系。线性结构数据元素与元素之间一对一的关系顺序表数组、链表、队列、栈树形结构数据元素与元素之间一对多的关系二叉树图形结构数据元素与元素之间多对多的关系网状结构2.2 物理结构顺序存储选取内存中连续空间进行存储代表顺序表数组特点内存空间必须连续数据元素的插入和删除需要移动后续大量数据访问元素效率高需要预分配内存空间分配不合适可能会造成内存浪费或者数组越界。链式存储可以选取非连续内存空间进行存储代表链式表特点内存空间可以不连续插入和删除数据元素方便访问数据必须要遍历不需要预分配空间可以根据数据动态存储。索引存储将要存储的元素关键字和存储位置构建索引表数据查找是通过查询索引表获取数据的真正存储位置。散列存储哈希存储将要存储的元素关键字和存储位置之间建立起对应关系这个关系称为哈希函数数据存储时按照哈希函数的映射进行存储数据查找时也按照哈希函数的映射进行查找。2.3 数据结构主要学习内容顺序表数组单向链式表双向链表循环链表队列栈二叉树哈希表2.4 知识储备C语言中的结构体和指针相关文章【C语言6】指针学习超详细【C语言7】构造数据类型学习动态内存分配相关文章【C语言8、9】内存管理、位运算及程序调试方法学习三、单向链表API应用程序接口创建链表链表插入头插、尾插链表删除查找修改链表遍历链表销毁3.1 创建链表链表数据类型的构建//链表结点类型typedefstructnode{intdata;//数据域保存的数据structnode*pnext;//指针域下一个结点的地址}Node_t;//链表对象类型typedefstructlink{Node_t*phead;//链表头节点指针intclen;//链表当前结点的个数}Link_t;单项链表的创建Link_t*create_link(){Link_t*plinkmalloc(sizeof(Link_t));if(NULLplink){printf(malloc error\n);returnNULL;}plink-pheadNULL;plink-clen0;returnplink;}3.2 链表插入头插从链表的前面插入数据intinsert_link_head(Link_t*plink,intdata){Node_t*pinsertmalloc(sizeof(Node_t));if(NULLpinsert){printf(malloc error\n);return-1;}pinsert-datadata;pinsert-pnextNULL;pinsert-pnextplink-phead;plink-pheadpinsert;plink-clen;return0;}尾插从链表的最后插入数据intinsert_link_tail(Link_t*plink,intdata){Node_t*pinsertmalloc(sizeof(Node_t));if(NULLpinsert){printf(mallocc error\n);return-1;}pinsert-datadata;pinsert-pnextNULL;if(is_empty_link(plink)){plink-pheadpinsert;}else{Node_t*ptmpplink-phead;while(ptmp-pnext!NULL){ptmpptmp-pnext;}ptmp-pnextpinsert;}plink-clen;return0;}3.3 链表删除头删intdelete_link_tail(Link_t*plink){if(is_empty_link(plink)){return-1;}elseif(NULLplink-phead-pnext){free(plink-phead);plink-pheadNULL;}else{Node_t*ptmpplink-phead;while(ptmp-pnext-pnext!NULL){ptmpptmp-pnext;}free(ptmp-pnext);ptmp-pnextNULL;}plink-clen--;return0;}尾删intdelete_link_tail(Link_t*plink){if(is_empty_link(plink)){return-1;}elseif(NULLplink-phead){free(plink-phead);plink-pheadNULL;}else{Node_t*ptmpplink-phead;while(ptmp-pnext-pnext!NULL){ptmpptmp-pnext;}free(ptmp-pnext);ptmp-pnextNULL;}plink-clen--;return0;}3.4 链表查找先用临时指针指向链表头部循环遍历每一个节点不断对比节点内存储的数据与目标数据若匹配成功直接返回当前节点的指针方便外部对该节点进行后续操作如果遍历到链表末尾仍未找到匹配数据就返回空指针代表查找失败。Node*find(Link*plink,intdata){Node*ptmpplink-phead;while(ptmp!NULL){if(ptmp-datadata){returnptmp;}ptmpptmp-pnext;}returnNULL;}3.5 链表修改传入待查找的原始数据 src 和要替换的新数据 des先调用查找函数定位存着 src 的节点若查找返回空指针说明链表没有该数据打印提示信息若找到对应节点则直接修改节点内部存储的数据为 des 并提示修改完成。该逻辑存在局限当链表中有多个相同 src 数值时只会修改第一个匹配到的节点。voidmodify(Link*plink,intdes,intsrc){Node*find_addrfind(plink,src);if(find_addrNULL){printf(link dont have this data\n);}else{find_addr-datades;printf(data %d modify %d\n,src,des);}}3.6 链表遍历定义临时游标从链表头节点开始循环依次读取并打印每个节点的数据每轮循环将游标移动到下一个节点直到游标为空即遍历完整条链表后换行结束。voidshow_link(Link*plink){Node*ptmpplink-phead;while(ptmp!NULL){printf(%d ,ptmp-data);ptmpptmp-pnext;}printf(\n);}3.7 链表销毁链表销毁是防止内存泄漏的关键函数负责释放链表全部堆区内存。循环判断链表不为空时重复调用头删函数逐个释放每一个动态创建的节点等所有节点内存全部释放完毕后再释放用来管理链表的结构体 plink。C 语言中用 malloc 申请的堆内存不会自动回收如果程序结束不执行销毁函数节点和链表结构体占用的内存会持续占用造成内存泄漏可使用 valgrind 工具检测该类内存问题。voiddestroy_link(Link*plink){while(!is_empty_link(plink)){del_head_link(plink);}free(plink);}用户自己申请的堆区空间使用完没有及时释放则造成内存泄露。检测程序有没有内存泄露valgrind内存错误检测工具GNU提供可以检测程序运行过程中的内存泄露情况以及野指针的使用情况等。使用方法安装valgrind工具sudo apt-get install valgrind使用valgrind./a.out valgrind--leak-checkfull./a.out