单链表的应用

上篇博客中,我们学习了单链表,为了更加熟练掌握这一知识点,就让我们将单链表的应用操练起来吧!

203. 移除链表元素 - 力扣(LeetCode)

思路一:遍历原链表,将值为val的节点释放掉。

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode Listnode;
struct ListNode* removeElements(struct ListNode* head, int val) {
    Listnode* newHead,*newTail;
    newHead=newTail=NULL;
    //遍历原链表
    while(pcur)
    {
        //找值不为val的值,插入到新链表中
        if(pcur->val!=val)
        {
            //链表为空
            if(bewHead==NULL)
            {
                newHead=newTail=pcur;
            }
            else{
                //链表不为空
                newTail->next=pcur;
                newTail=newTail->next;            }
        }
        pcur=pcur->next;
    }
    if(newTail){
    newTail->next=NULL;
    }
    return newHead;
}

LCR 024. 反转链表 - 力扣(LeetCode)

思路一:遍历原链表,将原链表的节点头插。

思路二:

创建三个指针,完成链表的翻转

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head){
//判断是否为空
   if(head==NULL)
   {
    return head;
   }
   ListNode*n1,*n2,*n3;//定义三个指针
   n1=NULL,n2=head,n3=head->next;
   while(n2)
   {
    n2->next=n1;
    n1=n2;
    n2=n3;
   if(n3)
   {
    n3=n3->next;
   }
}
 return n1;


}

876. 链表的中间结点 - 力扣(LeetCode)

思路一:直接返回node/2

思路二:快慢指针,slow每次走一步,fast每次走两步

21. 合并两个有序链表 - 力扣(LeetCode)

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if(list1==NULL)
    {
        return list2;//返回空链表
    }
    if(list2==NULL)
    {
        return list1;
    }
    ListNode*l1=list1;
    ListNode*l2=list2;
    //创建新的链表
    ListNode*newHead,*newTail;
    newHead=newTail=(ListNode*)malloc(sizeof(ListNode));
    while(l1&&l2)
    {
        if(l1->val&&l2->val)
        {
            if(newHead==NULL)
            {
                newHead=newTail=l1;
            }
            else
            {
               newTail->next=l2;
               newTail->next=newTail;
            }
            l2=l2->next;
        }
    }

    if(l2)
    {
        newTail->next=l2;
    }
    
    if(l1)
    {
        newTail->next=l1;
    }
    (ListNode*)ret=newHead->next;
    free(newHead);
    return ret;//newHead里面没有存储值
}

存在重复代码,如何优化呢?

我们可以定义一个头结点,也就是哨兵位。这个链表实际叫作带头链表。

环形链表的约瑟夫问题_牛客题霸_牛客网 (nowcoder.com)

第一步 创建带环链表

第二部 遍历带环链表

cpp 复制代码
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param n int整型 
 * @param m int整型 
 * @return int整型
 */
 typedef struct ListNode ListNode ;
 ListNode* buyNode(int x)
 {
    ListNode*node=(ListNode*)malloc(sizeof(ListNode));
    if(node==NULL)
    {
        exit(1);
    }
    node->val=x;
    node->next=NULL;
    return node;
 }

 ListNode* creatCirle(int n)
 {
    ListNode*phead=buyNode(1);
    ListNode*ptail=phead;
    for(int i=2;i<=n;i++)
    {
        ptail->next=buyNode(i);
        ptail=ptail->next;
    }
    //首位相连,链接成环
    ptail->next=phead;
    return ptail;
 }
int ysf(int n, int m ) {
    // write code here
    ListNode*prev=creatCirle(n);
    ListNode*pcur=prev->next;
    int count=1;
    while(pcur->next!=pcur)
    {
        if(count==m)//销毁pcur节点
        {
            prev->next=pcur->next;
            free(pcur);
            pcur=prev->next;
            count=1;//重新报数,count重新记为初始值
        }
        else {//不需要销毁节点
        prev=pcur;
        pcur=pcur->next;
        count++;
        }
    }
    //当链表中只有一个节点的情况跳出循环
    return pcur->val;


}

面试题 02.04. 分割链表 - 力扣(LeetCode)

思路一:在原链表上修改

若pcur的节点小于x,往后走

若pcur的节点大于或等于x,尾插在原链表后,删除旧节点

思路二:创建新链表,遍历原链表。若pcur的节点小于x,让它头插在新链表中。

若pcur的节点值大于或等于x,尾插。

思路三:创建新链表,小链表和大链表。

将小链表的尾结点和大链表的第一个有效节点首位相连。

cpp 复制代码
typedef struct ListNode ListNode;
struct ListNode* partition(struct ListNode* head, int x){
    if(head==NULL)
    {
        return NULL;
    }
    ListNode*lessHead,*lessTail;
    ListNode*greaterHead,*greaterTail;
    lessHead=lessTail=(ListNode*)malloc(sizeof(ListNode));
    greaterHead=greaterTail=(ListNode*)malloc(sizeof(ListNode));
    //遍历原链表,将原链表中的节点尾插到大小链表中
    ListNode*pcur=head;
    while(pcur)
    {
        if(pcur->val<x)
        {
            //尾插到小链表中
            lessTail->next=pcur;
            lessTail=lessTail->next;
        }
        else
        {
            //尾插到大链表中
            greaterTail->next=pcur;
            greaterTail=greaterTail->next;
        }
          pcur=pcur->next;  
    }
    //小链表的尾结点和大链表的头结点相连
    greaterHead->next=NULL;//若不写这一行,则代码出现死循环+next指针初始化
    lessTail->next=greaterHead->next;
    ListNode*ret=lessHead->next;
    free(lessHead);
    free(lessTail);
    lessHead=lessTail=NULL;
    return ret;


}

链表的分类

带头:是指链表带有哨兵位,即为头结点。

尾结点的next指针是否为空。

单链表:不带头单向不循环

双向链表:带头双向循环

相关推荐
你想考研啊32 分钟前
四、jenkins自动构建和设置邮箱
运维·jenkins
Code blocks34 分钟前
使用Jenkins完成springboot项目快速更新
java·运维·spring boot·后端·jenkins
snoopyfly~1 小时前
Ubuntu 24.04 LTS 服务器配置:安装 JDK、Nginx、Redis。
java·服务器·ubuntu
独行soc1 小时前
#渗透测试#批量漏洞挖掘#HSC Mailinspector 任意文件读取漏洞(CVE-2024-34470)
linux·科技·安全·网络安全·面试·渗透测试
BD_Marathon1 小时前
Ubuntu下Tomcat的配置
linux·ubuntu·tomcat
饥饿的半导体2 小时前
Linux快速入门
linux·运维
BD_Marathon2 小时前
Ubuntu:Tomcat里面的catalina.sh
linux·ubuntu·tomcat
BD_Marathon2 小时前
设置LInux环境变量的方法和区别_Ubuntu/Centos
linux·ubuntu·centos
Me4神秘2 小时前
Linux国产与国外进度对垒
linux·服务器·安全
zhaowangji2 小时前
ubuntu 20.04 安装中文输入法 (sougou pin yin)
linux·ubuntu