• C语言 Linux内核链表(企业级链表)


    //Linux内核链表(企业级链表)
    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define offscfof(TYPE,MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
    #define container_of(ptr,type,member) (type *)((char *)ptr-offscfof(type,member))
    
    typedef struct _node{
        struct _node *pNext;
    }Node;
    
    typedef struct _student1{
        int num;
        char name[20];
        Node mynode;
    }Student1;
    //说明:结构体也可以写成以下模式
    //typedef struct _student1{
    //    Node mynode;
    //    int num;
    //    char name[20];
    //}Student1;
    //这样一来,就不需要计算链表节点属性在结构体中的偏移量了,简单实用
    //我之所以写的复杂是为了深刻理解其原理
    
    
    //创建链表
    int SList_Create(Node **pout/*out*/);
    //获取链表长度
    int Get_List_Len(Node *pin/*in*/);
    //查找指定位置节点
    int FindNode(Node *pin/*in*/, Node **pdel/*out*/, int pos/*in*/);
    //插入指定位置节点
    int InsertOption(Node *pin/*in*/, Node *pnode/*in*/, int pos/*in*/);
    //删除指定节点
    int RemoveNode(Node *pin/*in*/, Node **pdel/*out*/, int pos/*in*/);
    
    void main(){
        //创建链表指针
        Node *phead;
        int i = 0,j=0;
        int ret = SList_Create(&phead);
        //说明:为什么我要创建一个无用的头节点
        //理由①:不创建一个头节点,那么初始化函数SList_Create()就没有必要存在
        //理由②:插入第一个节点的时候无法插入,以为没有头结点,所以插不进去第一个节点(这是主要理由)
        if (ret!=0)
        {
            printf("创建链表头节点失败!
    ");
        }
        //添加新节点
        Student1 *pa = (Student1 *)malloc(sizeof(Student1));
        pa->num = 1;
        strcpy(pa->name, "小米");
        pa->mynode.pNext = NULL;
        ret=InsertOption(phead, &pa->mynode, Get_List_Len(phead));
        if (ret != 0)
        {
            printf("添加新节点a失败!
    ");
            goto END;
        }
        Student1 *pb = (Student1 *)malloc(sizeof(Student1));
        pb->num = 1;
        strcpy(pb->name, "小明");
        pb->mynode.pNext = NULL;
        ret = InsertOption(phead, &pb->mynode, Get_List_Len(phead));
        if (ret != 0)
        {
            printf("添加新节点b失败!
    ");
            goto END;
        }
        //打印出所有的节点
        for (j = 0; j < Get_List_Len(phead); j++)
        {
            Node *temp = NULL;
            Student1 *temp2 = NULL;
            FindNode(phead, &temp, j);
            if (temp==NULL)
            {
                printf("查询节点失败
    ");
            }
            else{
                temp2 = container_of(temp, Student1, mynode);
                printf("学生的编号:%d;学生的姓名%s
    ", temp2->num, temp2->name);
            }
            
        }
    END:
        //删除所有链表节点
        while (Get_List_Len(phead)){
            Node *temp = NULL;
            Student1 *temp2 = NULL;
            RemoveNode(phead, &temp, 0);
            temp2 = container_of(temp, Student1, mynode);
            if (temp == NULL)
            {
                printf("节点删除失败!
    ");
            }
            else{
                if (temp2 != NULL)
                {
                    free(temp2);
                }
            }
        }
        //释放头节点
        if (phead==NULL)
        {
            free(phead);
        }
        system("pause");
    }
    
    //创建链表(顺序创建链表)
    int SList_Create(Node **pout/*out*/){
        int ERRO_MSG = 0;
        if (pout==NULL)
        {
            ERRO_MSG = 1;
            printf("pout==NULL erro msg:%d
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        Node *pM = (Node *)malloc(sizeof(Node));
        pM->pNext = NULL;
        *pout = pM;
        return ERRO_MSG;
    }
    
    //获取链表长度
    int Get_List_Len(Node *pin/*in*/){
        Node *pHead = NULL, *pCurrent = NULL;
        int index = 0;
        pCurrent = pin->pNext;
        while (pCurrent){
            pCurrent = pCurrent->pNext;
            index++;
        }
        return index;
    }
    
    //查找指定位置节点
    int FindNode(Node *pin/*in*/, Node **pnode/*out*/, int pos/*in*/){
        int ERRO_MSG = 0;
        if (pin == NULL || pnode == NULL)
        {
            ERRO_MSG = 1;
            printf("pin == NULL || pnode==NULL erro msg:%d
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        Node *pHead = NULL, *pCurrent = NULL, *pMalloc = NULL, *pPrior = NULL;
        pCurrent = pPrior = pin->pNext;
        if (pCurrent==NULL)
        {
            ERRO_MSG = 2;
            printf("链表中暂时没有数据  erro msg:%d
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        int index = 0;
        while (pCurrent){
            if (index==pos)
            {
                *pnode = pCurrent;
                break;
            }
            pPrior = pCurrent;
            pCurrent = pCurrent->pNext;
            index++;
        }
        if (*pnode==NULL)
        {
            ERRO_MSG = 3;
            printf("链表中没有找到该节点  erro msg:%d
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        return ERRO_MSG;
    }
    
    //插入指定位置节点
    int InsertOption(Node *pin/*in*/, Node *pnode/*in*/, int pos/*in*/){
        int ERRO_MSG = 0;
        if (pin == NULL || pnode==NULL)
        {
            ERRO_MSG = 1;
            printf("pin == NULL || pnode==NULL erro msg:%d
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        Node *pHead = NULL, *pCurrent = NULL, *pMalloc = NULL,*pPrior=NULL;
        pHead = pPrior = pin;
        pCurrent = pin->pNext;
        pMalloc = pnode;
        if (pCurrent==NULL)
        {
            if (pos==0)
            {
                pHead->pNext = pMalloc;
                return ERRO_MSG;
            }
            else{
                ERRO_MSG = 2;
                printf("链表为空,无法在指定位置插入节点
    ", ERRO_MSG);
                return ERRO_MSG;
            }
        }
        int index = 0;
        while (pCurrent){
            if (pos == index)
            {
                pPrior->pNext = pMalloc;
                pMalloc->pNext = pCurrent;
                return ERRO_MSG;
            }
            pPrior = pCurrent;
            pCurrent = pCurrent->pNext;
            index++;
        }
        pPrior->pNext = pMalloc;
        return ERRO_MSG;
    }
    
    //删除指定节点
    int RemoveNode(Node *pin/*in*/, Node **pdel/*out*/, int pos/*in*/){
        int ERRO_MSG = 0;
        if (pin == NULL || pdel==NULL)
        {
            ERRO_MSG = 1;
            printf("pin == NULL || pdel==NULL erro msg:%d
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        Node *pHead = NULL, *pCurrent = NULL, *pMalloc = NULL, *pPrior = NULL;
        pHead = pPrior = pin;
        pCurrent = pin->pNext;
        if (pCurrent==NULL)
        {
            ERRO_MSG = 2;
            printf("你要删除的链表为空! erro msg:%d
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        int index = 0, flag = 0;
        while (pCurrent){
            if (index == pos)
            {
                pPrior->pNext = pCurrent->pNext;
                *pdel = pCurrent;
                break;
            }
            pPrior = pCurrent;
            pCurrent = pCurrent->pNext;
            index++;
        }
        if (*pdel==NULL)
        {
            ERRO_MSG = 3;
            printf("链表中没有该位置的节点! erro msg:%d
    ", ERRO_MSG);
            return ERRO_MSG;
        }
        return ERRO_MSG;
    }

  • 相关阅读:
    sql语句3
    Android中PopupWindow的用法(位置、动画、焦点)
    JS+CSS实现的二级下拉导航菜单
    【强烈推荐】myFocustab打造的各种功能的选项卡切换
    【荐】JS+CSS实现兼容好带缓冲的动感网页右键菜单
    JS打造仿QQ的精简版折叠菜单
    JS打造类似QQ的折叠菜单
    很不错的JS+CSS滑动门
    jQuery智能判断是否是当前导航并加标记
    采用jQuery连缀写法的折叠菜单
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/5569603.html
Copyright © 2020-2023  润新知