数据结构之链表增删查改(最详细注释和最清晰思路,附完整代码)

2023-11-20

PZK学数据结构之链表(史上最详细思路和代码注释)(完整代码我放在最后面了,可以直接跑,方便大家cv编程)


文章目录

前言

在增删的指定节点操作就用到了查,大家可以看完增删的前两个就去看看查是怎么操作的,然后方便对指定节点操作。
本篇文章是交大家如何用结构体指针实现增删查改,

一、链表是什么?

百度百科链表:链表是一种物理存储单元上非连续、非顺序的存储结构,
数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

我的理解:多个有指针域的结构体的通过指针顺序链接在一起, 在内存中的存储是散落的

2.1图解数组和链表的存储

在内存如下存储:在这里插入图片描述

---------------------------------------------------------------------------------------------------------------------------------------------------------------

2.2简单实现链表的两种方法,第一种是用结构体,第二种是用结构体指针

代码如下(示例):

2.2.1实现链表1
#include <stdio.h>
#include <stdlib.h>
struct Test//结构体定义
{
   int data;
   struct Test *next;
};

int main()
{
   struct Test t1={1,NULL};
   struct Test t2={2,NULL};
   struct Test t3={3,NULL};

   t1.next=&t2;//链表精髓在这,每个节点的next存放的是下一个节点的地址。这样就连接起来了。
   t2.next=&t3;
}
2.2.1实现链表2
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node
{
    int data;
    struct node * next;
}node,*pnode;//node是取别名,pnode是类型,结构体指针类型

//struct node *  pnode
//创建头节点,初始化函数。返回头节点的指针。
pnode init()
{
    pnode head = (pnode )malloc(sizeof(node));   //用malloc开辟空间,此时pnode == struct node *
  
    if(head == NULL)//此时做一个容错判断,如果没有开辟成功,打印错误
    {
        perror("head fault");
    }
   
    head->data = 0;//开辟空间之后里面是没有值的,最好给数据域和指针域分别赋值
    head->next = NULL;//指针没有指向,指向NULL就ok,防止其乱指向
   
    return head;//返回头节点指针,方便我们以后调用

}


---------------------------------------------------------------------------------------------------------------------------------------------------------------

二、本文实现的几个功能

链表的增加
链表的删除
链表的查找
链表的改动


---------------------------------------------------------------------------------------------------------------------------------------------------------------

三、链表的增加

在内存如下演示:
在这里插入图片描述

实现思路:(博主比较懒,三种插法只详细写了一个思路,思路都大同小异,我在每个插法代码的前面都画了内存操作图,里面有简单思路,每一行代码里面都给了注释,不理解的可以评论区留言呀)
第一步,创建新节点,然后把传递的值赋值给新节点
pnode pnew = (pnode )malloc(sizeof(node));//用malloc开辟空间,类型是pnode,大小是一个结构体的大小

第二步,写一个容错判断,如果pnew==NULL,说明创建不成功,直接退出

第三步:链接新节点到链表头下一个节点,何为链接,无非就是把下个节点的地址赋值给头节点的next;
pnew->next = head->next;//head->next原本存的是第二个节点的地址,现在把它赋值给新节点,那么是不是新节点的下一个就是原先的第二个节点了,就是实现图中1

第四步:把头结点和新节点连接起来
head->next = pnew;//此时,我们在把新节点和头节点链接起来,这样就是头节点指向新节点了,pnew本身就是一个指针


3.1头插法:每次都在头结点的后面插入

//每次都在头结点的后面增加,简称头插法
/****************************************************************
 * 函数名: insertHead
 * 参  数: head  链表的头节点指针
 *         data  需要插入节点数据
 * 返回值: 链表中节点个数
 *         节点的个数保存在head的data中。
 ****************************************************************/
int insertHead(node* head,int data)
{
    //第一步:创建新节点,存入数据
    pnode pnew = (pnode )malloc(sizeof(node));//用malloc开辟空间,类型是pnode,大小是一个结构体的大小

    if(NULL == pnew)//容错判断新创建的节点是否成功
    {
        perror("head NULL");
        exit(0);//不成功就输出错误,然后退出
    }
   
    pnew->data = data;//把传进来的值赋值给新节点

    //第二步:链接新节点到链表头下一个节点,何为链接,无非就是把下个节点的地址赋值给头节点的next;
    //head的next为空的情况
    pnew->next = head->next;//head->next原本存的是第二个节点的地址,现在把它赋值给新节点,那么是不是新节点的下一个就是原先的第二个节点了

    //第三步:head不为空,把头节点的next指针指向新的节点
    head->next = pnew;//此时,我们在把新节点和头节点链接起来,这样就是头节点指向新节点了,pnew本身就是一个指针
                      //当第二步赋值的时候,头节点与原先的第二个节点链接自动断开

    //第四步:节点个数加一
    (head->data)++;//因为我们头节点的数据域存的是节点个数
    //第五步:返回头节点中节点数据;
    return head->data;
}

---------------------------------------------------------------------------------------------------------------------------------------------------------------

3.2尾插法:每次都在链表的最后面插入

在内存如下演示:
在这里插入图片描述


/****************************************************************
 * 函数名: insertEnd
 * 参  数: head  链表的头节点指针
 *         data  需要插入节点数据
 * 返回值: 链表中节点个数
 *         节点的个数保存在head的data中。
 ****************************************************************/
int insertEnd(pnode head,int data)
{
    //第一步:定义临时指针
    node* ptmep = head;
    //第二部:遍历链表,找最后一个节点
    while( ptmep->next != NULL)
    {
        ptmep = ptmep->next;//指针偏移
    }
    //循环完之后,ptemp的next已经为NULL了
    //第三步:创建新节点
    pnode pnew = (pnode)malloc(sizeof(node));//malloc开辟空间
  
    //第四步:给节点赋值
    pnew->data = data;
    //第五步:新节点插入到链表末尾
    pnew->next = NULL;//尾插法,新节点需放在最后,所以新节点后面没有节点了,指向null
    ptmep->next = pnew;//原最后一个节点指向新节点,那么原最后一个节点就成为了倒数第二个节点
  
    //第六步:返回链表长度
    (head->data)++;
    return head->data;//也可以直接return ++(head->data);一样的效果
    }
   

---------------------------------------------------------------------------------------------------------------------------------------------------------------

3.3指定位置插法:在指定位置插入新节点

在内存如下演示:
在这里插入图片描述


/*********************************************
 * 函数名:insert
 * 参数:  head头节点指针
 *        pos  需要插入的位置
 *        data 需要插入的数据
 * 返回值: 链表的节点个数
 * 作用:  在pos的位置插入一个节点
*****************************************************/
int insert(pnode head,int pos,int data)
{
    // 第0步:判断pos是否超过节点个数
    if(pos > head->data)
    {
        printf("无法插入指定位置,程序退出\n");
        exit(0);
    }
    // 第一步:定义临时变量,用来遍历到每个节点
    pnode ptemp = head;//赋值后,ptemp就相当与头节点,不过只是一个临时变量,程序结束就会释放
    // 第二步: 创建节点,赋值
    pnode pnew = (pnode)malloc(sizeof(node));
    pnew->data = data;
    //第三步:找到pos的上一个节点
    int i = 0;
    for ( i = 0; i < pos-1; i++)//for循环的第二个条件,小于pos,就循环到pos
    {
        ptemp = ptemp->next;
    }
    
   // 第四步:新节点连接到链表中
   //4.1 新节点连接到第pos的节点上
   pnew->next = ptemp->next;//p->next->next指向pos的下一个节点
   //4.2 pos前一个节点(ptemp)的next指向新节点
   ptemp->next = pnew;
    //第五步:返回节点数
    (head->data)++;
    return head->data;
}

---------------------------------------------------------------------------------------------------------------------------------------------------------------

四、链表的删除

4.1头删法:删除头结点的最后一个节点

在内存如下演示:
在这里插入图片描述


/*********************************************
 * 函数名:deleteEnd
 * 参数:  head头节点指针     
 * 返回值: 删除后的节点个数    
 * 作用: 在链表中删除最后一个节点
*****************************************************/
int deleteEnd(pnode head)
{
    //第一步:定义临时变量,遍历,判断空
     if(IsEmpty(head))
    {
        printf("链表为空,无法删除\n");
        return head->data;
    }
    pnode ptemp = head;
    //第二步:找倒数第二个节点 ptemp->next->next == NULL
    while(ptemp->next->next != NULL)
    {
        ptemp = ptemp->next;
    }
    //第三步:释放最后一个节点
    free(ptemp->next);
    //第四步:把删除后剩下的最后一个节点的next=NULL;
    ptemp->next = NULL;
    //第五步:数据元素个数减1
    return  --(head->data);
   
}

---------------------------------------------------------------------------------------------------------------------------------------------------------------

4.2尾删法:删除链表的最后一个节点

在内存如下演示:
在这里插入图片描述


/*********************************************
 * 函数名:deleteEnd
 * 参数:  head头节点指针     
 * 返回值: 删除后的节点个数    
 * 作用: 在链表中删除最后一个节点
*****************************************************/
int deleteEnd(pnode head)
{
    //第一步:定义临时变量,遍历,判断空
    if(IsEmpty(head))
    {
        printf("链表为空没法删除\n");
        return head->data;
    }
    pnode ptemp = head;
    //第二步:找倒数第二个节点 ptemp->next->next == NULL
    while(ptemp->next->next != NULL)
    {
        ptemp = ptemp->next;
    }
    //第三步:释放最后一个节点
    free(ptemp->next);
    //第四步:把删除后剩下的最后一个节点的next=NULL;
    ptemp->next = NULL;
    //第五步:数据元素个数减1
    return  --(head->data);
   
}

---------------------------------------------------------------------------------------------------------------------------------------------------------------

4.3指定删法:删除链表的指定节点

在内存如下演示:
在这里插入图片描述


/*********************************************
 * 函数名: deletePos
 * 作 用: 删除pos位置的节点
 * 参 数: head  链表的头指针
 *      pos   需要删除的节点位置
 * 返回值: 返回链表中的节点个数 
**********************************************/
int deletePos(pnode head,int pos)
{
    //判断链表是否为NULL
    if(IsEmpty(head))
    {
        printf("链表为null没法删除\n");
        return head->data;
    }
    //第一步:定义临时变量
    pnode ptemp = head;
    pnode pPos = NULL;
    //第二步:找到pos位置的前一个节点(保存pos位置)
    for (int i = 0; i < pos -1 ; i++)
    {
        ptemp =ptemp->next;
        if (!ptemp)
        {
            printf("\n位置不存在\n");
            return head->data;
        }
    }
    pPos = ptemp->next;  //保存pos位置指针
    //第三步:把pos的前一个位置的next指针指向pos下一个位置。
    ptemp->next = pPos->next;
    //第四步:释放pos位置节点
    free(pPos);
    pPos = NULL;
    //第五步:节点个数减1(返回节点个数)
    return --(head->data);
    

}


---------------------------------------------------------------------------------------------------------------------------------------------------------------

五、链表的查找,可以查找指定值的节点,也可以找指定节点的值

在内存如下演示:
在这里插入图片描述


/*********************************************
 * 函数名:findNode
 * 参数:  head头节点指针
 *        data 需要超找的数据
 * 返回值: 如果成功返回找到的data位置的指针
 *         如果失败返回NULL
 * 作用: 在链表中查找data的所在位置。
*****************************************************/
pnode findNode(pnode head,int data)
{
    // 第一步:定义临时变量,用来遍历到每个节点
    pnode ptemp = head; 
    int num = 0;  //记录data的位置
    //第二步:遍历整改链表
    while (NULL !=  ptemp->next ) 
    {
        
        ptemp = ptemp->next;
        num++;
        //第三步: 比对是否找到
        if(ptemp->data == data)
        {
            printf("data=%d在%d的位置\n",data,num);
            return ptemp;
        }
    }
    printf("%d在链表中没找到\n",data);
    return NULL;

}

六、链表的改动,思路图我就没画了本人比较懒能偷一点懒是一点,大致思路就是在五查找的基础上去替换值,可以替换指定位置的值(知道位置用for循环),也可以替换指定值的值(指定值,用while循环,用值对比)

/**********************************************************
 * 函数名:changeData
 * 参数:  head头节点指针
 *        pos  需要修改的数据的位置
 *        data 需要修改的数据
 * 返回值: 如果成功返回ture,失败返回false
 * 作  用:把链表中pos位置的数据修改成data
 ***********************************************************/
int changeData(pnode head,int pos,int data)
{
    // 第0步:判断pos是否超过节点个数,节点5,要是head只有4,就没有5节点来改变
    if(pos > head->data)
    {
        printf("pos超出节点,无法修改\n");
    }
    // 第一步:定义临时变量,用来遍历到每个节点
    pnode ptemp = head;
    int i = 0;
    //第三步:找到pos节点
    for(i=0;i<pos;i++)
    {
        ptemp = ptemp->next;
    }    
    //上面一步一步偏移完之后,ptemp已经遍历到pos位置了就等与pos
    //第四步:替换数据
    ptemp->data = data;
    //这里最好是弄一个返回值,来返回是否成功,也可以打印出来
    return head->data;
   
}

总结,大家不会可以评论也可以私信我一起讨论,欢迎大家评论指导。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*作 者:pzk
  功 能:实现链表的增删查改
*第一个功能:头插法,每次都在头节点的后一个位置插入(链接到头节点上)
*第二个功能:尾插法,每次插入都在链表的最后一个节点,使原本指向NULL的最后一个节点指向新节点
*第三个功能:指定位置插入,用for循环,找到指定节点的上一个节点,把新节点插入到指定节点的上一个节点的后面
*第四个功能:改变指定位置的值(也可以用值去查找,把旧值用新值代替,例如我想吧原本存2的指针改为存3)
*第五个功能:查找,查找我们想要的值,并返回指定值的位置的指针
*/
typedef struct node
{
    int data;
    struct node * next;
}node,*pnode;//node是取别名,pnode是类型,结构体指针类型

//struct node *  pnode
//创建火车头,初始化函数。返回火车头的指针。
pnode init()
{
    pnode head = (pnode )malloc(sizeof(node));   //用malloc开辟空间,此时pnode == struct node *
  
    if(head == NULL)//此时做一个容错判断,如果没有开辟成功,打印错误
    {
        perror("head fault");
    }
   
    head->data = 0;//开辟空间之后里面是没有值的,最好给数据域和指针域分别赋值
    head->next = NULL;//指针没有指向,指向NULL就ok,防止其乱指向
   
    return head;//返回头节点指针,方便我们以后调用

}


//第二步:头插法,在头节点的后面插入一个元素
/****************************************************************
 * 函数名: insertHead
 * 参  数: head  链表的头节点指针
 *         data  需要插入节点数据
 * 返回值: 链表中节点个数
 *         节点的个数保存在head的data中。
 ****************************************************************/
int insertHead(node* head,int data)
{
    //第一步:创建新节点,存入数据
    pnode pnew = (pnode )malloc(sizeof(node));//用malloc开辟空间,类型是pnode,大小是一个结构体的大小

    if(NULL == pnew)//容错判断新创建的节点是否成功
    {
        perror("head NULL");
        exit(0);//不成功就输出错误,然后退出
    }
   
    pnew->data = data;//把传进来的值赋值给新节点

    //第二步:链接新节点到链表头下一个节点,何为链接,无非就是把下个节点的地址赋值给头节点的next;
    //head的next为空的情况
    pnew->next = head->next;//head->next原本存的是第二个节点的地址,现在把它赋值给新节点,那么是不是新节点的下一个就是原先的第二个节点了

    //第三步:head不为空,把头节点的next指针指向新的节点
    head->next = pnew;//此时,我们在把新节点和头节点链接起来,这样就是头节点指向新节点了,pnew本身就是一个指针
                      //当第二步赋值的时候,头节点与原先的第二个节点链接自动断开

    //第四步:节点个数加一
    (head->data)++;//因为我们头节点的数据域存的是节点个数
    //第五步:返回头节点中节点数据;a/*  */
    return head->data;
}

// 写尾部插入。
int insertEnd(pnode head,int data)
{
    //第一步:定义临时指针
    node* ptmep = head;
    //第二部:遍历链表,找最后一个节点
    while( ptmep->next != NULL)
    {
        ptmep = ptmep->next;//指针偏移
    }
    //循环完之后,ptemp的next已经为NULL了
    //第三步:创建新节点
    pnode pnew = (pnode)malloc(sizeof(node));//malloc开辟空间
  
    //第四步:给节点赋值
    pnew->data = data;
    //第五步:新节点插入到链表末尾
    pnew->next = NULL;//尾插法,新节点需放在最后,所以新节点后面没有节点了,指向null
    ptmep->next = pnew;//原最后一个节点指向新节点,那么原最后一个节点就成为了倒数第二个节点
  
    //第六步:返回链表长度
    (head->data)++;
    return head->data;//也可以直接return ++(head->data);一样的效果
   
}
/**********************************************************
 * 函数名:changeData
 * 参数:  head头节点指针
 *        pos  需要修改的数据的位置
 *        data 需要修改的数据
 * 返回值: 如果成功返回ture,失败返回false
 * 作  用:把链表中pos位置的数据修改成data
 ***********************************************************/
int changeData(pnode head,int pos,int data)
{
    // 第0步:判断pos是否超过节点个数,节点5,要是head只有4,就没有5节点来改变
    if(pos > head->data)
    {
        printf("pos超出节点,无法修改\n");
    }
    // 第一步:定义临时变量,用来遍历到每个节点
    pnode ptemp = head;
    int i = 0;
    //第三步:找到pos节点
    for(i=0;i<pos;i++)
    {
        ptemp = ptemp->next;
    }    
    //上面一步一步偏移完之后,ptemp已经遍历到pos位置了就等与pos
    //第四步:替换数据
    ptemp->data = data;
    //这里最好是弄一个返回值,来返回是否成功,也可以打印出来
    return head->data;
   
}

/*********************************************
 * 函数名:insert
 * 参数:  head头节点指针
 *        pos  需要插入的位置
 *        data 需要插入的数据
 * 返回值: 链表的节点个数
 * 作用:  在pos的位置插入一个节点
*****************************************************/
int insert(pnode head,int pos,int data)
{
    // 第0步:判断pos是否超过节点个数
    if(pos > head->data)
    {
        printf("无法插入指定位置,程序退出\n");
        exit(0);
    }
    // 第一步:定义临时变量,用来遍历到每个节点
    pnode ptemp = head;//赋值后,ptemp就相当与头节点,不过只是一个临时变量,程序结束就会释放
    // 第二步: 创建节点,赋值
    pnode pnew = (pnode)malloc(sizeof(node));
    pnew->data = data;
    //第三步:找到pos的上一个节点
    int i = 0;
    for ( i = 0; i < pos-1; i++)//for循环的第二个条件,小于pos,就循环到pos
    {
        ptemp = ptemp->next;
    }
    
   // 第四步:新节点连接到链表中
   //4.1 新节点连接到第pos的节点上
   pnew->next = ptemp->next;//p->next->next指向pos的下一个节点
   //4.2 pos前一个节点(ptemp)的next指向新节点
   ptemp->next = pnew;
    //第五步:返回节点数
    (head->data)++;
    return head->data;
}

/*********************************************
 * 函数名:findNode
 * 参数:  head头节点指针
 *        data 需要超找的数据
 * 返回值: 如果成功返回找到的data位置的指针
 *         如果失败返回NULL
 * 作用: 在链表中查找data的所在位置。
*****************************************************/
pnode findNode(pnode head,int data)
{
    // 第一步:定义临时变量,用来遍历到每个节点
    pnode ptemp = head;
    //记录data的位置
    int n=0;
    //第二步:遍历整改链表
    //第三步: 比对是否找到
    while(ptemp->next != NULL)//当循环到倒数第二个节点时,会先在里面偏移,偏移后对比值
    {
        ptemp = ptemp->next;
        n = n+1;//记录节点的位置,每偏移一次就加1
        if(ptemp->data == data)//如果链表此时位置的值与传进来的指定值一样,就打印出来
        {
            printf("找到了!%d在%d的位置",ptemp->data,n);
            return ptemp;//返回此时节点的指针,并退出这个函数
        }
    }
    printf("没找到");
    return NULL;
       
      
}
// 判断链表是否为空,如果为空则返回真,否则返回假
bool IsEmpty(pnode head)
{
    if(head->next == NULL)//也可以用头节点的值判断,其值为0说明没有其他节点,判断head是不是指向空也行
    {
        return true;
    }
    return false;
}

/*********************************************
 * 函数名:deleteEnd
 * 参数:  head头节点指针     
 * 返回值: 删除后的节点个数    
 * 作用: 在链表中删除最后一个节点
*****************************************************/
int deleteEnd(pnode head)
{
    //第一步:定义临时变量,遍历,判断空
    if(IsEmpty(head))
    {
        printf("链表为空没法删除\n");
        return head->data;
    }
    pnode ptemp = head;
    //第二步:找倒数第二个节点 ptemp->next->next == NULL
    while(ptemp->next->next != NULL)
    {
        ptemp = ptemp->next;
    }
    //第三步:释放最后一个节点
    free(ptemp->next);
    //第四步:把删除后剩下的最后一个节点的next=NULL;
    ptemp->next = NULL;
    //第五步:数据元素个数减1
    return  --(head->data);
   
}
/*********************************************
 * 函数名: deleteHead
 * 作 用: 删除第一个数据节点
 * 参 数: head  链表的头指针  
 * 返回值: 返回链表中的节点个数 
**********************************************/
int deleteHead(pnode head)
{
    //第0步:先判断是否链表为空
    if(IsEmpty(head))
    {
        printf("链表为空,无法删除\n");
        return head->data;
    }
    //第一步:定义临时变量,保存头的下一个节点
    pnode ptemp = head->next;
    //第二步:头节点的next连接到第二个节点
    head->next = head->next->next;//
    //第三步:释放第一个数据节点
    free(ptemp);
    ptemp->next = NULL;//把ptemp指针指向空,防止其乱指
    //第四步:链表节点个数减1
    (head->data)--;
    return head->data;
}
/*********************************************
 * 函数名: deletePos
 * 作 用: 删除pos位置的节点
 * 参 数: head  链表的头指针
 *      pos   需要删除的节点位置
 * 返回值: 返回链表中的节点个数 
**********************************************/
int deletePos(pnode head,int pos)
{
    //判断链表是否为NULL
    IsEmpty(head);
    //第一步:定义临时变量
    pnode ptemp = head;
    pnode pnew;
    //第二步:找到pos位置的前一个节点(保存pos位置)
    for(int i=0;i<pos-1;i++)
    {
        ptemp = ptemp->next;
        if (!ptemp)
        {
            printf("\n位置不存在\n");
            return head->data;
        }
    }

    //保存pos位置指针
    pnew = ptemp->next;
    //第三步:把pos的前一个位置的next指针指向pos下一个位置。
    ptemp->next = ptemp->next->next;//把下下个指针赋给自己用pnew操作就是ptemp->next=pnew->next
    //第四步:释放pos位置节点
    free(pnew);//注意pnew->next和pnew是有区别的
    pnew->next = NULL;
    //第五步:节点个数减1(返回节点个数)
    return --(head->data);

}


/************************************************
 * 函数名: deletePos
 * 作 用: 对链表进行排序,使用选择排序算法
 * 参 数: head  链表的头指针
 *      
 * 返回值: 无 
 ************************************************/
//这个不建议初学者去玩,学好增删查改就很ok了,一定要自己多敲代码
void LinkSort(pnode head)
{
    //第一步:定义临时变量
    pnode ptemp = head;
    pnode p = head;
    int temp = 0;//用于交换两个变量
    while(ptemp->next != NULL)
    {
        ptemp = ptemp->next;
        p = ptemp;
        while(p->next)
        {
            p = p->next;
            if (p->data < ptemp->data)
            {
                temp = ptemp->data;
                ptemp->data = p->data;
                p->data = temp;
            } 
        }
      
    }
}


void show(pnode head)
{
    printf("链表有%d个节点\n",head->data);//因为我们的头节点的data存的是节点个数
    // 第一步:定义临时变量,用来遍历到每个节点
    pnode ptemp = head;
    //第二步:判断是否为最后一个节点
    while(ptemp->next != NULL)//如果头节点->next为空,那么此时就是一个空链表,后面没有节点
    {
        //第三步:寻找下一个节点
        ptemp = ptemp->next;//这个地方可以自己思考理解一下,是怎么实现的
                            //原理很简单,ptemp->next原本是ptemp的下一个节点,这么一赋值,ptemp自动往右边移了一个节点
        printf("%d-->",ptemp->data);//打印的时候,指针需要用->来操作,结构体的话可以不是指针类型可以用点操作,ptemp.data,结构体指针不能这么用
    }
    printf("NULL\n");
       
}
int main()
{
    pnode head = init();
    //头部插入5个元素
    int i = 0;
    for(i=0;i<3;i++)
    {
           insertHead(head,i*10); 
    }
    //尾部插入5个元素
    for(i=0;i<3;i++)
    {
           insertEnd(head,i*100); 
    }
    
    show(head);
    //changeData(head,5,6666);
    //show(head);
    //insert(head,6,9999);
    //show(head);
    //findNode(head,6666);
    //deleteHead(head);
    //deleteEnd(head);
    deletePos(head,2);
    show(head);
    

    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构之链表增删查改(最详细注释和最清晰思路,附完整代码) 的相关文章

  • 前端例程20211213:网页去色(以灰度形式显示)

    文章目录 前言 实现与演示 前言 在每年的一些特殊的日子 比如公祭日等 很多网站会将页面整体去色以灰度形式显示 以示哀悼 这里将对网页中实现该功能进行简单说明 实现与演示 使用CSS的 filter grayscale 属性可以给元素添加灰

随机推荐

  • 主进程退出后子进程还会存在吗?_深度好文

    干了这碗鸡汤 我急切地盼望着可以经历一场放纵的快乐 纵使巨大的悲哀将接踵而至 我也在所不惜 太宰治 人间失格 大家好 这里是周日凌晨4点 仍在笔耕不辍的程序喵大人 下面隆重推出我呕心沥血 耗时半个月完成的精心力作 01 什么是进程 标准定义
  • Element Plus 配置自动按需引入后,手动引入组件,组件样式丢失

    起因 最近在尝试使用 Element Plus 写一些简单的页面 跟着官方文档走配置了自动按需引入 npm install D unplugin vue components unplugin auto import vite config
  • IDEA全局搜索框打不开,全局搜索不全,全局搜索不到解决办法

    IDEA默认全局搜索快捷键是Ctrl Shift F 当我在使用IDEA的全局搜索时 发现IDEA的全局搜索快捷键不起作用 无法弹出全局搜索框 此时想到了应该是快捷键被占用了 首先想到的就是搜狗输入法 打开搜狗输入法设置 高级 把这个简繁切
  • Python 基于BP神经网络的鸢尾花分类

    本文用Python实现了BP神经网络分类算法 根据鸢尾花的4个特征 实现3种鸢尾花的分类 算法参考文章 纯Python实现鸢尾属植物数据集神经网络模型 2020 07 21更新 增加了分类结果可视化result visualization
  • Elasticsearch 索引模板:优化大数据搜索与分析

    Elasticsearch 是一个强大的分布式搜索和分析引擎 广泛应用于处理大数据量的搜索和分析任务 为了提高搜索效率和数据组织结构的一致性 Elasticsearch 提供了索引模板 template 的功能 索引模板允许我们在创建索引时
  • 《python语言程序设计》第5章 第23题 贷款计算

    LOAN AMOUNT 10000 number years 5 NUMBER OF YEAR number years 12 interest rate 5 month rate interest rate 1200 print f Lo
  • springboot跳转页面

    SpringBoot里面只有src目录 在src main resources下面有两个文件夹 static 和 templates springboot默认static中放静态页面 而templates中放动态页面 themleaf和fr
  • Egret游戏通用开发框架

    地址 https github com yicaoyimuys EgretGameEngine 简介 现在这套代码已经有几个项目都在使用了 主要用于各项目组间统一开发规范 便于开发人员调整 以及新手快速熟悉项目 支持Egret2 0 x和2
  • C#写的34401A串口232数据读取程序

    首先呢 请先设置惠普表为Talk only模式 也就是31 还不明白的自己查手册去 另外 各个表设置不一样 比如我这里2块表就不一样 一块是7位数据位 even校验 另一块是8位数据位 none校验 具体的可以看看表里的i o那里的设置 数
  • GPIO的两种引脚规则:BCM与BOARD

    树莓派 raspberry 针脚在python中BCM与BOARD模式的区别 在python程序中定义的GPI针脚有两种模式 BCM模式 BOARD模式 BCM模式 例如 GPIO setmode GPIO BCM 测试结果如下 物理针脚1
  • pycharm注释快捷键Ctrl+/

    行注释 取消行注释 Ctrl 块注释 Ctrl Shift
  • ArcGIS部分问题解决办法

    ArcGIS部分常见问题解决办法 最近在学习ArcGIS过程中 进行某些操作选项总是会会发生错误 不仅仅我自己一个人是这样 周围好多同学也是经常在操作的过程中报错 所以就很突发奇想把这段时间遇到的问题统一写下来 也是为了自己以后忘掉可以直接
  • 系统调用:用户级函数如何通过INT 80中断进入操作系统内核

    以printf 打印内核中的一段字符串为例 printf 是用户函数无法进入内核 因此需要进行系统调用 进入内核的方式是使用int 0x80中断 printf 函数想要进入系统内核是通过系统调用write 实现 位置 linux lib w
  • Usbkey原理介绍

    不好意思 百度来的 大家一起学习吧 文库中竟然收费5个币 Usbkey原理介绍 一 usbkey实现身份认证原理 采用冲击响应的认证方法 登录时在服务器端和客户端同时进行计算 客户端计算前要先验证USER PIN 通过后在硬件中使用HMAC
  • OD华为机试 23

    篮球比赛 描述 篮球 5V5 比赛中 每个球员拥有一个战斗力 每个队伍的所有球员战斗力之和为该队伍的总体战斗力 现有10个球员准备分为两队进行训练赛 教练希望2个队伍的战斗力差值能够尽可能的小 以达到最佳训练效果 给出10个球员的战斗力 如
  • docker搭建hadoop hdfs完全分布式集群

    1 制作hadoop镜像 参见 https www cnblogs com rmxd p 12051866 html 该博客中只参考制作镜像部分 固定IP及启动集群的部分应该跳过 这里注意 在做好的镜像里 要安装 which 工具 否则在执
  • DFS的个人理解和测试例题

    深度优先搜索 DFS 是一种搜索手段 可以理解为 它从某个位置 起点 开始 沿着一条路不断地向前走直到尽头 然后退后一步 去走其它没走过的路 没有的话 再退后一步 再去选择 直到找到目的地 终点 例如下图 从A 起点 开始走 先走ABD 在
  • 【MySQL】Ubuntu22.04安装MySQL8数据库详解

    00 目录 文章目录 00 目录 01 安装MySQL 02 配置MySQL 03 查看MySQL状态 04 登录MySQL数据库 05 问题讨论 06 附录 01 安装MySQL 1 1 更新软件源 deng local code 3li
  • MQTT.fx连接、订阅、发布OneNet平台(新版)

    第一步 打开MQTT fx 点击设置按钮 第二步 命名的话随便起 中文英文皆可以 token的下载地址 https open iot 10086 cn doc v5 develop detail 242 第三步 token生成密码 时间戳转
  • 数据结构之链表增删查改(最详细注释和最清晰思路,附完整代码)

    PZK学数据结构之链表 史上最详细思路和代码注释 完整代码我放在最后面了 可以直接跑 方便大家cv编程 文章目录 PZK学数据结构之链表 史上最详细思路和代码注释 完整代码我放在最后面了 可以直接跑 方便大家cv编程 前言 一 链表是什么