ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2-另一种形式的单向链表

2022-01-25 21:03:34  阅读:201  来源: 互联网

标签:struct currNode 形式 单向 next 链表 link 节点 plist


笔记

另一种形式的单向链表

节点结构体并不存储数据,只有一个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;
}

标签:struct,currNode,形式,单向,next,链表,link,节点,plist
来源: https://www.cnblogs.com/TaXueWuYun/p/15843399.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有