当前位置:   article > 正文

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

链表的增删改查

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
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;//返回头节点指针,方便我们以后调用

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

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

二、本文实现的几个功能

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


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

三、链表的增加

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

实现思路:(博主比较懒,三种插法只详细写了一个思路,思路都大同小异,我在每个插法代码的前面都画了内存操作图,里面有简单思路,每一行代码里面都给了注释,不理解的可以评论区留言呀)
第一步,创建新节点,然后把传递的值赋值给新节点
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

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

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);一样的效果
    }
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

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

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

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

四、链表的删除

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);
   
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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

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);
   
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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

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);
    

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

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

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

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


/*********************************************
 * 函数名: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;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

六、链表的改动,思路图我就没画了本人比较懒能偷一点懒是一点,大致思路就是在五查找的基础上去替换值,可以替换指定位置的值(知道位置用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;
   
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

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

#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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/706872
推荐阅读
相关标签
  

闽ICP备14008679号