单链表的应用

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

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

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

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

/**
 * 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)

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

思路二:

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

/**
 * 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)

/**
 * 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)

第一步 创建带环链表

第二部 遍历带环链表

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @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,尾插。


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


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

 
 
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指针是否为空。

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

双向链表:带头双向循环

相关文章
|
4天前
|
存储 编译器 C语言
【数据结构】深入浅出理解链表中二级指针的应用
【数据结构】深入浅出理解链表中二级指针的应用
32 0
|
4天前
|
存储 缓存 算法
C++链表解析:从基础原理到高级应用,全面掌握链表的使用
C++链表解析:从基础原理到高级应用,全面掌握链表的使用
59 0
|
4天前
|
算法
链表中快慢指针的应用
链表中快慢指针的应用
|
5月前
数据结构循环链表之介绍和应用 | 第一套
数据结构循环链表之介绍和应用 | 第一套
28 0
|
9月前
|
存储 算法 Java
Java LinkedList:探索双向链表的灵活应用
在Java编程中,LinkedList是一种重要的数据结构,它在内存中以双向链表的形式存储数据,为我们提供了一种动态而灵活的数据管理方式。本文将引导您深入了解Java中的LinkedList,包括其特点、用法、与ArrayList的比较,以及实际应用场景。
|
10月前
|
存储 C++
指针及其应用5——指针链表
指针及其应用5——指针链表
|
存储
【线性表】—带头哨兵卫单链表的应用
【线性表】—带头哨兵卫单链表的应用
102 0
|
机器学习/深度学习 存储 人工智能
【数组与链表算法】矩阵算法在程序中常见的简单应用 | C++
数组与链表都是相当重要的结构化数据类型,也都是典型线性表的应用。线性表用于计算机中的数据存储结构,按照内存存储的方式基本上可以分为以下两种:静态数据结构和动态数据结构。数组类型就是一种典型的静态数据结构,动态数据结构又称为链表。在我前面的算法系列文章都细致的对二者的使用方法做过讲解。
159 0
【数组与链表算法】矩阵算法在程序中常见的简单应用 | C++
|
存储 Java
Java单链表的应用实例
Java单链表的应用实例
168 0
Java单链表的应用实例