2-另一种形式的单向链表
笔记
另一种形式的单向链表
节点结构体并不存储数据,只有一个next指针元素。然后约定好数据结构体预留四个字节(结构体定义时的最上方,地址的低四字节)。当数据指针和节点指针互相转换时,next元素就映射至数据预留的四字节,即可用来做指针指向下一节点。这样可以让数据和链表更分离,链表可以不再维护数据。
代码
start0.c
#include<stdlib.h>
#include<stdio.h>
//节点
struct linkNode{
void* next;
};
//管理节点
typedef struct{
struct linkNode head;
int m_size;
}linkListType;
//初始化链表
linkListType* init_link(){
linkListType* llt = malloc(sizeof(linkListType));
return llt;
}
//按位置插入数据
void insert_link(linkListType* plist,int pos, void* data){
if(NULL == plist){
return;
}
if(pos < 0 || pos > plist->m_size){
pos = plist->m_size;
}
//将data转成linkNode类型,这样linkNode的低4字节和data的低4字节重合
struct linkNode* myNode = data; //myNode既是要插入节点的指针,它的前4字节又被提供出来做next字段
struct linkNode* currNode = &(plist->head);
//找到要插入位置的前驱节点
for(int i=0;i<pos;i++){
currNode = currNode->next;
}
myNode->next = currNode->next; //要插入节点的next指向下一节点
currNode->next = myNode; //前驱节点的next指向要插入的节点
plist->m_size++;
}
//遍历
void foreach_link(linkListType* plist,void(*myforeach)(void*)){
if(NULL == plist){
return;
}
struct linkNode* currNode = &plist->head;
for(int i=0;i<plist->m_size;i++){
currNode = currNode->next;
myforeach(currNode);
}
}
//通过位置删除链表节点
void remove_link(linkListType* plist, int pos){
if(NULL == plist){
return;
}
if(pos < 0 || pos >= plist->m_size){
pos = plist->m_size-1;
}
//找到位置的前置节点
struct linkNode* currNode = &plist->head;
for(int i=0; i<pos; i++){
currNode = currNode->next;
}
//记录要删除的数据
struct linkNode* delNode = currNode->next;
//修改指向,将前驱节点的next指向 要删除节点 的后驱节点
currNode->next = delNode->next;
//不要在这里释放delNode,链表不维护数据
plist->m_size--;
}
//清空链表
void clear_link(linkListType* plist){
if(NULL == plist){
return;
}
struct linkNode* currNode = &plist->head;
struct linkNode* delNode = NULL;
for(int i=0; i<plist->m_size; i++){
delNode = currNode; //要清除的节点
currNode = currNode->next;
delNode = NULL;
}
plist->m_size = 0;
}
//按照约定,数据的低4字节存储next指针
struct Persion{
void* node;
char m_name[64];
int m_age;
};
void myForEach(void* data){
struct Persion* p = data;
printf("name=%s\tage=%d\n",p->m_name, p->m_age);
}
int main(){
linkListType* plist = init_link();
struct Persion p1 = {NULL,"aaa",10};
struct Persion p2 = {NULL,"bbb",20};
struct Persion p3 = {NULL,"ccc",30};
insert_link(plist,0,&p1);
insert_link(plist,0,&p2);
insert_link(plist,1,&p3);
foreach_link(plist,myForEach);
remove_link(plist,1);
printf("------------------------\n");
foreach_link(plist,myForEach);
clear_link(plist);
printf("------------------------\n");
foreach_link(plist,myForEach);
free(plist);
return 0;
}