自学内容网 自学内容网

【C】链表的创建、打印、插入、删除等

链表两个概念:
1.普通链表    data定义数据类型指针(不够灵活)
2.通用链表 data定义void*(可以接受任何数据类型的指针地址)

注意:头结点是哨兵结点,没有数据及其地址

1.创建结点 

通过结构体定义一个结点:
typedef struct node_t
{
    int val;//记录节点链表的位置
    void *data;//存放数据字段
    struct node_t *pnext;//下一结点地址
}NODE_T;

2.创建链表,返回头结点

步骤:
1.创建一个链表结点
2.开辟内存,并去清空内存(可以使用calloc函数,malloc不能清理内存)
3.赋值
 NODE_T *List_Init()
{
    //1.创建一个链表结点
    NODE_T *head=NULL;//一开始指向0,需要开内存
    //开辟内存
//    head=(NODE_T *)malloc(sizeof(NODE_T));//未清空内存
    head=(NODE_T *)calloc(1,sizeof(NODE_T));//开辟空间,清空内存
    if(head==NULL)
    {
        printf("开辟内存空间失败!\n");
        return NULL;
    }
    head->data=NULL;
    head->pnext=NULL;
    head->val=0;
    return head;
}

3.链表添加结点(默认尾插)

把节点添加到链表
head:头结点指针    data:要插入数据地址
    void List_Add(NODE_T *head,void *data)
{
    NODE_T *ptmp=head;//保存头结点
    NODE_T *newNode=NULL;
    int tmp_val=0;

    //找到链表尾部结点
    while(ptmp->pnext!=NULL)
    {
        tmp_val=ptmp->val;
        ptmp=ptmp->pnext;
    }

    //在内存中开辟新节点空间
    newNode=(NODE_T *)calloc(1,sizeof(NODE_T));
    newNode->data=data;

    newNode->val=++tmp_val;
    newNode->pnext=NULL;

    ptmp->pnext=newNode;

}

4.打印链表

里面的数据data,因为定义无类型指针,这里指向结构体

void printList(NODE_T *head)
{
    NODE_T *ptmp=head;
    while(ptmp!=NULL)
    {

        if(ptmp->data!=NULL)
        {
            printf("age=%d\n",((PACK_T*)(ptmp->data))->age);
        }
        ptmp=ptmp->pnext;
    }
}

5.获取链表的结点个数

获取链表有多少结点,链表第一个结点data无数据,叫哨兵结点
int getListCount(NODE_T *head)
{
    int count=0;
    NODE_T *ptmp=head;
    while(ptmp->pnext!=NULL)
    {
        count++;
        ptmp=ptmp->pnext;


    }
    return count;//链表有效结点的个数

}


6.插入结点(尾插)

pos:第几个结点,data:插入的数据    

int insertList(NODE_T *head,int pos,void *data)
{
    NODE_T *ptmp=head;
    NODE_T *newNode=NULL;
    int num=0;
    //1.找pos在链表位置
    while(ptmp->pnext!=NULL)
    {
        ptmp=ptmp->pnext;//跳开哨兵结点
        num++;
        if(num==pos)
        {
            newNode=(NODE_T*)calloc(1,sizeof(NODE_T));
            if(newNode==NULL)
            {
                printf("calloc error!\n");
                exit(0);
            }
            newNode->data=data;

            //以下两个顺序不能颠倒
            newNode->pnext=ptmp->pnext;
            ptmp->pnext=newNode;//指向新的
            return 0;
        }
    }
    return -1;
}

7.删除指定结点

1.找到要删除的结点位置,要保存前一个结点指针
2.定义两个指针,pre:前个结点
int deleteNodeByPos(NODE_T *head,int pos)
{
    //找到要删除的结点位置
    //要保存前一个结点指针
    //定义两个指针,pre:前个结点    
    NODE_T *ptmp=head->pnext,*pre=head;
    int num=0;
    while(ptmp!=NULL)
    {
        num++;
        if(num==pos)
        {
            pre->pnext=ptmp->pnext;//把前一个结点指向后一个结点
            free(ptmp);
            return 1;

        }
        //如果不是匹配的位置ptmp与pre往后移
        pre=pre->pnext;
        ptmp=ptmp->pnext;
    }
    return -1;
}

8.指定位置返回数据

void *getListDataByPos(NODE_T *head,int pos)
{
    NODE_T *ptmp=head;
    int num=0;
    while(ptmp->pnext!=NULL)
    {
        ptmp=ptmp->pnext;
        num++;
        if(num==pos)
        {
            return ptmp->data;
        }
    }
    return NULL;
}

9.释放整个链表

void freeList(NODE_T *head)
{
    NODE_T *ptmp=head;
    while(ptmp!=NULL)
    {
        head=head->pnext;//首相移动到下一个结点
        free(ptmp);//可以释放ptmp,因为ptmp还是指向移动之前的结点
        ptmp=head;//再把移动后的结点赋值ptmp
    }
}


 


原文地址:https://blog.csdn.net/weixin_74154742/article/details/143818504

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!