zoukankan      html  css  js  c++  java
  • C_数据结构_链表的链式实现

    传统的链表不能实现数据和链表的分离,一旦数据改变则链表就不能用了,就要重新开发。

     如上说示:外层是Teacher,里面小的是node.

    #ifndef _MYLINKLIST_H_
    #define _MYLINKLIST_H_
    
    typedef void LinkList;//链表上下文,任意类型
    
    typedef struct _tag_LinkListNode
    {
        struct _tag_LinkListNode* next;//包含下一个节点的地址
    }LinkListNode;//节点
    
    
    
    LinkList* LinkList_Create();
    
    void LinkList_Destroy(LinkList* list);
    
    void LinkList_Clear(LinkList* list);
    
    int LinkList_Length(LinkList* list);
    
    int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
    
    LinkListNode* LinkList_Get(LinkList* list, int pos);
    
    LinkListNode* LinkList_Delete(LinkList* list, int pos);
    
    #endif
    #define  _CRT_SECURE_NO_WARNINGS 
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    #include "linklist.h"
    
    typedef struct _tag_LinkList//这个链表的上下文信息,类似于handle.这里面是链表的头结点和链表的长度。
    {
        LinkListNode header;
        int        length;
    }TLinkList;
    
    
    
    LinkList* LinkList_Create()  //O(1)
    {
        TLinkList *tmp = NULL;
    
        tmp = (TLinkList *)malloc(sizeof(TLinkList));
        if (tmp == NULL)
        {
            printf("func LinkList_Create() err 
    ");
            return NULL;
        }
        memset(tmp, 0, sizeof(TLinkList));
        tmp->length = 0;
        tmp->header.next = NULL; //
        return tmp;
    }
    
    void LinkList_Destroy(LinkList* list)  //O(1)
    {
        if (list == NULL)
        {
            return ;
        }
        free(list);//只把上下文信息释放。因为加进去的Teacher对象是局部的,main函数执行完后会自动释放,所以这里不用手动释放。
        return ;
    }
    
    void LinkList_Clear(LinkList* list)   //O(1)
    {
        TLinkList *tList = NULL;
        tList = (TLinkList *)list;
        if (tList == NULL)
        {
            return ;
        }
        tList->header.next = NULL;
        tList->length = 0;
    
        return ;
    }
    
    int LinkList_Length(LinkList* list)  //O(1)
    {
        TLinkList *tList = NULL;
        tList = (TLinkList *)list;
        if (tList == NULL)
        {
            return -1;
        }
        return tList->length;
    }
    
    int LinkList_Insert(LinkList* list, LinkListNode* node, int pos)  //在pos位置插入节点,先连接后面的再连接前面的。
    {
        int                i = 0;
        LinkListNode    *current = NULL;
        TLinkList        *tList = NULL;
        if (list==NULL || node==NULL || pos<0)//node为新节点
        {
            return -1;
        }
        tList = (TLinkList *)list;
        
        
    
        current = &(tList->header);//节点要取地址给指针
        for (i=0; i<pos; i++)//链表节点序号从0开始
        {
            current = current->next;//current为pos位置前面的节点
        }
        //先连接后面节点在连接前面节点
        node->next = current->next;
    
        //前面的链表 连接 新结点
        current->next = node;
    
        tList->length ++;
        return 0;
    }
    
    LinkListNode* LinkList_Get(LinkList* list, int pos)  //O(n)
    {
        int                i = 0;
        LinkListNode    *current = NULL;
        TLinkList        *tList = NULL;
    
        tList = (TLinkList *)list;
    
        if (list==NULL || pos<0)
        {
            return NULL;
        }
    
        current = &(tList->header); //赋值指针变量初始化
        for (i=0; i<pos; i++)
        {
            current = current->next;
        }
        return current->next;
    }
    
    LinkListNode* LinkList_Delete(LinkList* list, int pos) //O(n)
    {
        int                i = 0;
        LinkListNode    *current = NULL;
        LinkListNode    *ret = NULL;
        TLinkList        *tList = NULL;
    
        tList = (TLinkList *)list;
        if (list==NULL || pos<0)
        {
            return NULL;
        }
    
        current = &(tList->header);
        for (i=0; i<pos; i++)
        {
            current = current->next;
        }
        ret = current->next; //缓存要删除的结点
    
        current->next = ret->next;
    
        tList->length --;
    
        return ret;
    }
    #define  _CRT_SECURE_NO_WARNINGS 
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    #include "linklist.h"
    
    
    /*
    typedef struct _Node
    {
        struct _Node *next;
    }Node;
    
    typedef struct _Teacher1
    {
        char    name[32];
        int        age ;
        Node node;
    }Teacher1;
    
    
    typedef struct _Teacher2
    {
        Node node;
        char    name[32];
        int        age ;
        
    }Teacher2;
    
    Teacher2 t2;
    */
    
    typedef struct _Teacher
    {
        LinkListNode node;    //偏移量:从node元素找到Teacher的地址。写到上面则node的内存首地址和Teacher对象的内存首地址重叠了。
        char        name[32];
        int            age ;
    }Teacher;
    
    
    void main()
    {
        LinkList    *list = NULL;
        int            i = 0;
    
        Teacher t1, t2, t3, t4, t5, t6;//main函数结束这几个变量释放
        t1.age = 31;
        t2.age = 32;
        t3.age = 33;
        t4.age = 34;
        t5.age = 35;
        t6.age = 36;
    
        list = LinkList_Create();
    
        //思考1: 业务节点 和 链表算法是如何分离
        //思考2:  业务节点的生命周期 归谁管...
    
    
        //插入元素
        LinkList_Insert(list, (LinkListNode *)&t1, 0);//t1地址和node地址是重叠的
        LinkList_Insert(list, (LinkListNode *)&t2, 0);
        LinkList_Insert(list, (LinkListNode *)&t3, 0);
        LinkList_Insert(list, (LinkListNode *)&t4, 0);
        LinkList_Insert(list, (LinkListNode *)&t5, 0);
        LinkList_Insert(list, (LinkListNode *)&t6, 3);
    
    
        //遍历链表
        for (i=0; i<LinkList_Length(list); i++)
        {
            Teacher *tmp = (Teacher *)LinkList_Get(list, i);
            if (tmp == NULL)
            {
                return ;
            }
            printf("age:%d 
    ", tmp->age);
        }
    
    
        //删除链表结点
        while (LinkList_Length(list) > 0)
        {
            Teacher *tmp = (Teacher *)LinkList_Delete(list, 0);
            if (tmp == NULL)
            {
                return ;
            }
            printf("age:%d 
    ", tmp->age);
        }
    
        LinkList_Destroy(list);
    
    
        printf("hello...
    ");
        system("pause");
        return ;
    }
  • 相关阅读:
    OpenCV4【6】-改变颜色空间
    OpenCV4【5】-图像基本运算
    OpenCV4【4】- 图像基本操作
    OpenCV4【3】- GUI特性:轨迹栏作为调色板
    OpenCV4 【2】- GUI特性 :绘图功能 与 鼠标事件
    OpenCV4【1】- 入门用法
    numpy
    可变对象 及其 作为 函数参数 的注意点
    关于m个苹果每天吃一个或者两个,有几种吃法
    kali之win10 linux子系统环境变量冲突解决办法
  • 原文地址:https://www.cnblogs.com/yaowen/p/4803617.html
Copyright © 2011-2022 走看看