单向链表装载用户自定义数据的c语言实现 linklistpackagenode.h 和 linklistpackagenode.c
来源:互联网 发布:淘宝美工的电脑配置 编辑:程序博客网 时间:2024/05/29 02:46
linklistpackagenode.h 文件
#ifndef _LINKLIST_PACKAGENODE_H_#define _LINKLIST_PACKAGENODE_H_#include <stdio.h>#include <stdlib.h>#include <string.h>//单向链表//链表操作精髓在于操作关系节点,引入辅助指针pcurrent,pnext.从表头开始遍历各关系节点。//让业务节点包含关系节点,并把关系节点放在业务的首地址//业务的首地址就是关系节点的地址,统一转化//让无序的数据通过指针组成链表,联系起来//1,指针指向谁就把谁的地址赋给指针//2,分清楚链表的操作逻辑和辅助指针变量之间的关系//3, 链表是链式存储的,无顺序,单向的,找到3必须先找到2,//找到2必须先找到1,找到1必先找到0,再找到头,故引入辅助指针,不可以[]操作//实现上层调用和底层分离,不让调用用户知道数据结构typedef void List;typedef void UserData;#ifndef bool#define bool int#define true 1#define false 0#endif//链表就是有很多表格组成,刚开始创建表头格,//业务节点创建后来的表格,通过关系节点连接起来/**链表只创建了一个链表头,next指向null。后边添加的节点是在业务节点中产生的。**///小节点,等待被业务节点包含。//由小节点之间的关系连接业务节点。//被业务节点放在首部,小节点地址与业务节点首地址重合//链表的算法和业务分离,STL思想//定义小节点是有联系的 ,小节点的链表typedef struct _tag_LinkListConnectedNode{ struct _tag_LinkListConnectedNode* next;}LinkListConnectedNode;//定义链表头, 头部链表typedef struct _tag_LinkList{ LinkListConnectedNode head; //小节点 int length; //小节点的个数就相当于业务节点的个数}LinkList;//定义用户链表typedef struct _tag_LinkListUser{ LinkListConnectedNode head; //小节点 UserData* item;}LinkListUser;//用户定义的数据业务模型只要包含关系节点,且关系的节点的地址与表头的关系节点地址相当//都是每个表格的首地址即可,业务节点就可以与表头串起来//typedef struct _tag_LinkListData//{// LinkListConnectedNode node; //关系节点// Teacher teacher; //业务数据//}LinkListData;List* LinkList_create();bool LinkList_destory(List* list);bool LinkList_clear(List* list);int LinkList_getLength(List* list);bool LinkList_insertOneNode(List* list ,UserData* listuserdata, int pos);UserData* LinkList_getOneNode(List* list, int pos );UserData* LinkList_deleteOneNode(List* list, int pos);bool LinkList_deleteAllNode(List* list);#endif
linklistpackagenode.c 文件
#include "linklistpackagenode.h"#include <stdio.h>#include <stdlib.h>#include <string.h>//底层函数分配链表头和业务链表的内存,注意内存管理//底层函数分配业务链表关系连接节点的内存,业务链表包含了待操作数据的节点//对链表的操作实际是通过关系连接节点的操作完成的//各链表的首地址就是关系连接节点的地址//链表头的首地址就是第一个关系连接节点的地址//链表头不存业务数据//链表操作精髓在于操作关系节点,引入辅助指针pcurrent,pnext.从表头开始遍历各关系节点。//每次增加新业务节点时,只需业务创建业余节点,通过关系节点连接起来//业务节点和链表头都要包含关系节点。List* LinkList_create(){ //只创建一个头结点 List* ret = NULL; LinkList* templinklist = NULL; templinklist = (LinkList*)malloc(sizeof(LinkList)); memset(templinklist,0,sizeof(LinkList)); templinklist->head.next = NULL; templinklist->length = 0; ret = (List*)templinklist; return ret;}//销毁链表先清空链表在释放表头内存bool LinkList_destory(List* list){ bool ret; LinkList* templinklist = NULL; if (list == NULL) { return false; } templinklist = (LinkList*)list; ret = LinkList_clear((List*)templinklist); if (ret == false) { return false; } if (templinklist != NULL) { free(templinklist); templinklist = NULL; } return true;}//清空链表先删除所有业务节点,只保留表头,注意内存释放bool LinkList_clear(List* list){ bool ret; LinkList* templinklist = NULL; if (list == NULL) { return false; } templinklist = (LinkList*)list; ret = LinkList_deleteAllNode((List*)templinklist); if (ret == false) { return false; } if (templinklist != NULL) { templinklist->length = 0; templinklist->head.next = NULL; } return true;}int LinkList_getLength(List* list){ int ret = 0; LinkList* templinklist = NULL; if (list == NULL) { return -1; } templinklist = (LinkList*)list; ret = templinklist->length; return ret;}//用户节点转换为链表节点,底层函数分配链表业务节点的内存bool LinkList_insertOneNode(List* list ,UserData* userdata, int pos){ LinkList* templinklist = NULL; LinkListConnectedNode* pcurrent = NULL; //辅助指针 LinkListConnectedNode* linklistconnectednode = NULL; int i = 0; //业务链表 LinkListUser* linklistuser = NULL; if (list == NULL || userdata == NULL || pos < 0) { return false; } templinklist = (LinkList*)list; //底层函数为业务链表分配内存 linklistuser = (LinkListUser*)malloc(sizeof(LinkListUser)); //初始化 memset(linklistuser,0,sizeof(LinkListUser)); if (linklistuser == NULL) { return false; } //代操作的数据转换为业务链表的节点 linklistuser->item = userdata; //业务链表首地址就是关系连接的节点,利用关系连接节点操作 linklistconnectednode = (LinkListConnectedNode*)linklistuser; //辅助指针指向链表的头部,带头的链表,头部之后就是0位置存业务节点; //头部只存小节点,不存业务节点。头部只是指向整个链表的首地址 pcurrent = &(templinklist->head); //辅助指针从头部跳到(pos-1) 处;头部、0、1、2、。。 for ( i = 0; (i < pos && (pcurrent->next != NULL)); i++) { pcurrent = pcurrent->next; } //头,0,1,2,3,4, 要在3号插入,pcurrent 指向2,pcurrent->next 指向3 //插入新节点后,新节点的next应该指向原来的3即上面的pcurrent->next,pcurrent->next应该指向新节点了 //当前节点的next 指向要插入新节点的next linklistconnectednode->next = pcurrent->next; //当前节点的next指向要插入新节点的地址 pcurrent->next = linklistconnectednode; templinklist->length++; return true;}//得到链表的业务节点UserData* LinkList_getOneNode(List* list, int pos ){ LinkList* templinklist = NULL; LinkListConnectedNode* pcurrent = NULL; //辅助指针 UserData* ret = NULL; int i = 0; //业务链表 LinkListUser* linklistuser = NULL; if (list == NULL || pos < 0) { return NULL; } templinklist = (LinkList*)list; if (templinklist->length <= 0 || pos >= templinklist->length) { return NULL; } //辅助指针指向链表的头部,带头的链表,头部之后就是0位置存业务节点; //头部只存小节点,不存业务节点。头部只是指向整个链表的首地址 pcurrent = &(templinklist->head); //辅助指针指向链表头部 //辅助指针从头部跳到(pos-1) 处;头部、0、1、2、。。 for (i = 0; (i < pos && (pcurrent->next != NULL)); i++) //跳pos次,到pos-1处,刚开始指向头部,跳1次指向0 { pcurrent = pcurrent->next; } //得到业务链表节点 linklistuser = (LinkListUser*)(pcurrent->next); ret = (UserData*)(linklistuser->item); return ret;}//删除链表的业务节点,由于业务节点时底层分配的,还需要底层释放UserData* LinkList_deleteOneNode(List* list, int pos){ LinkList* templinklist = NULL; LinkListConnectedNode* pcurrent = NULL; //辅助指针 LinkListConnectedNode* pdelete = NULL; //缓存要删除的节点 UserData* ret = NULL; int i = 0; LinkListUser* linklistuser = NULL; if (list == NULL || pos < 0) { return NULL; } templinklist = (LinkList*)list; if (templinklist->length <= 0 || pos >= templinklist->length) { return NULL; } //辅助指针指向链表的头部,带头的链表,头部之后就是0位置存业务节点; //头部只存小节点,不存业务节点。头部只是指向整个链表的首地址 pcurrent = &(templinklist->head); //辅助指针指向链表头部 //辅助指针从头部跳到(pos-1) 处;头部、0、1、2、。。 for (i = 0; (i < pos && (pcurrent->next != NULL)); i++) //跳pos次,到pos-1处,刚开始指向头部,跳1次指向0 { pcurrent = pcurrent->next; } //得到要删除的节点 pdelete = pcurrent->next; pcurrent->next = pdelete->next; templinklist->length--; //删除的业务节点 linklistuser =(LinkListUser*)pdelete; ret = (UserData*)linklistuser->item; //释放业务节点内存 if (linklistuser != NULL) { free(linklistuser); linklistuser = NULL; } return ret;}bool LinkList_deleteAllNode(List* list){ LinkList* templinklist = NULL; if (list == NULL) { return false; } templinklist = (LinkList*)list; while(templinklist->length > 0) { LinkList_deleteOneNode(list,0); } return true;}/***********************以下为测试代码************************//*//方法1:在业务节点中定义链表的一格的关系节点//typedef struct _tag_Teacher{// LinkListConnectedNode node;// int age;// char name[64];//}Teacher;//方法2:把业务直接定义到链表一格的关系节点之下//用户定义的数据业务模型只要包含关系节点,//且关系的节点的地址与表头的关系节点地址相当//都是每个表格的首地址即可,业务节点就可以与表头串起来typedef struct _tag_Teacher{ int age; char name[64];}Teacher;void main(){ int k = 0; List* list = NULL; Teacher t1,t2,t3,t4,t5; t1.age = 21;t2.age = 22;t3.age = 23;t4.age = 24;t5.age = 25; list = LinkList_create(); if (list == NULL) { printf("list创建失败"); } //头插法,插入元素 //业务节点强制转换为ListNode* ,ListNode* 强制转换为小节点LinkListConnectedNode*; LinkList_insertOneNode(list,(UserData*)&t1,0); LinkList_insertOneNode(list,(UserData*)&t2,0); LinkList_insertOneNode(list,(UserData*)&t3,0); LinkList_insertOneNode(list,(UserData*)&t4,0); LinkList_insertOneNode(list,(UserData*)&t5,0); printf("链表长度是:%d \n", LinkList_getLength(list)); //遍历链表 for (k = 0; k < LinkList_getLength(list); k ++) { Teacher* teachertemp = (Teacher* )LinkList_getOneNode(list,k); printf("老师%d的年龄是%d \n",k+1,teachertemp->age); } LinkList_deleteAllNode(list); printf("链表长度是:%d \n", LinkList_getLength(list)); LinkList_destory(list); system("pause");}*/
可能会调用其它头文件会源文件,如果遇到,请翻看我的其它博客,对其头文件或源文件的实现方式。
good luck !
阅读全文
1 0
- 单向链表装载用户自定义数据的c语言实现 linklistpackagenode.h 和 linklistpackagenode.c
- C语言单向链表的实现
- C语言实现的单向链表
- 单向链表的C语言实现
- C语言单向链表的实现
- c语言单向链表的实现
- C语言单向链表的实现
- C语言单向链表的实现
- C语言单向链表的实现
- C语言单向链表的实现
- C语言单向链表的实现
- C语言实现链表之单向链表(十三)获取数据对应的结点
- 单向链表C语言实现
- 自己实现C语言单向链表
- C语言实现单向链表
- 单向循环链表C语言实现
- C语言基础 - 实现单向链表
- C语言实现 单向链表
- 创建RDD
- 跟我学C语言(第四天)
- keras一些example代码理解
- OVS源码结构分析
- 我眼里的正则表达式入门教程
- 单向链表装载用户自定义数据的c语言实现 linklistpackagenode.h 和 linklistpackagenode.c
- JavaScript 代码造成页面出现乱码问题解决
- mac docker 修改 daemon.json文件
- 设计模式6大设计原则解读——迪米特法则
- 456. 132 Pattern
- C# 锯齿数组
- 湖南省第六届程序设计竞赛---台球碰撞
- docker 容器镜像删除
- switch语句解决成绩等级问题