单链表的应用(1)

移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
单链表的应用(1)_第1张图片
思路:(1)创建三个结构体指针,分别代表一条新链表的头newhead,一条新链表的尾newtail,还有一个用于循环旧链表的pcur
(2)循环旧链表,当pcurval不等于函数参数中的val时:1.当新链表为空时,将新链表的newheadnewtail赋值为pcur 2.当新链表不为空时,newtailnext指向pcurnewtail赋值为newtialnext
(3)运行完一个结点pcur赋值为pcurnext
(4)当运行结束时,代表旧链表运行完毕,当最后一个结点等于val时,newtail的值不会是空,而是旧链表最后一个结点的值,因此我们需要进行判断,当newtail不为空时,需要将newtail置空,最后返回newhead即可

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* newhead=NULL;
    struct ListNode* newtail=NULL;
    struct ListNode* pcur=head;
    while(pcur)
    {
        if(pcur->val != val)
        {
            if(newhead == NULL)
            {
                newhead=newtail=pcur;
            }
            else
            {
                newtail->next=pcur;
                newtail=newtail->next;
            }
        }
        pcur=pcur->next;
    }
    if(newtail)
    {
        newtail->next=NULL;
    }
    return newhead;
}

单链表的应用(1)_第2张图片

反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
单链表的应用(1)_第3张图片
思路:(1)若链表为空,则直接返回空
(2)若不为空,创建三个结构体指针分别为n1,n2,n3,将n1赋值为NULLn2赋值为headn3赋值为head->next
(3)以n2为循环条件进行遍历,每次运行都将n2next赋值为n1n1赋值为n2n2赋值为n3,若n3不为空则n3赋值为n3next(下图为第一次和第二次循环图)
(4)又因为n2n3最后的位置都为NULL,所以最后返回n1即可。
单链表的应用(1)_第4张图片

struct ListNode* reverseList(struct ListNode* head) 
{
    if(head==NULL)
    {
        return NULL;
    }
    struct ListNode* n1=NULL;
    struct ListNode* n2=head;
    struct ListNode* n3=head->next;
    while(n2)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
        {
            n3=n3->next;
        }
    }
    return n1;
}

单链表的应用(1)_第5张图片

合并两个有序链表

将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
单链表的应用(1)_第6张图片

思路:(1)判断传入的参数list1、list2是否为空,为空则返回另一个
(2)创建四个结构体指针,newhead代表新链表的头,newtail代表新链表的尾,pcur1pcur2分别用来遍历list1list2
(3)若pcur1pcur2都不为空则进入循环,当pcur1val大于pcur2val,判断newhead是否为空,为空则将newheadnewtail赋值为pcur1,不为空则进行新链表结点的插入,即将newtailnext赋值为pcur1newtail赋值为newtailnextpcur1小于等于pcur2时同理,只需将pcur1改为pcur2即可
(4)当循环结束,判断pcur1pcur2是否为空,某个不为空时,将newtailnext赋值为不为空的pcur,最后返回newhead即可

  • 不带头单向不循环链表
//不带头单向不循环链表
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if(list1 == NULL)
    {
        return list2;
    }
    if(list2 == NULL)
    {
        return list1;
    }
    struct ListNode* newhead=NULL;
    struct ListNode* newtail=NULL;
    struct ListNode* pcur1=list1;
    struct ListNode* pcur2=list2;
    while(pcur1 && pcur2)
    {
        if((pcur1->val) < (pcur2->val))
        {
            if(newhead == NULL)
            {
                newhead=newtail=pcur1;
            }
            else
            {
                newtail->next=pcur1;
                newtail=newtail->next;
            }
            pcur1=pcur1->next;
        }
        else
        {
            if(newhead == NULL)
            {
                newhead=newtail=pcur2;
            }
            else
            {
                newtail->next=pcur2;
                newtail=newtail->next;
            }
            pcur2=pcur2->next;
        }
    }
    if(pcur1 != NULL)
    {
        newtail->next=pcur1;
    }    
    if(pcur2 != NULL)
    {
        newtail->next=pcur2;
    }
    return newhead;
}
  • 带头单向不循环链表
    思路:(1)newheadnewtail的初始值不再是NULL,而是一个没有val值的结点,相当于是一个哨兵位。因此就不再需要判断newhead是否为空。
    (2)最后需要将mallocnewhead指针释放,需要创捷一个新结构体指针rehead赋值为newheadnext,便可进行newhead的释放,最后返回rehead即可
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if(list1 == NULL)
    {
        return list2;
    }
    if(list2 == NULL)
    {
        return list1;
    }
    struct ListNode* newhead=(struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* newtail=newhead;
    struct ListNode* pcur1=list1;
    struct ListNode* pcur2=list2;
    while(pcur1 && pcur2)
    {
        if((pcur1->val) < (pcur2->val))
        {
            newtail->next=pcur1;
            newtail=newtail->next;
            pcur1=pcur1->next;
        }
        else
        {
            newtail->next=pcur2;
            newtail=newtail->next;
            pcur2=pcur2->next;
        }
    }
    if(pcur1 != NULL)
    {
        newtail->next=pcur1;
    }    
    if(pcur2 != NULL)
    {
        newtail->next=pcur2;
    }
    struct ListNode* rehead=newhead->next;
    free(newhead);
    newhead=NULL;
    return rehead;
}

单链表的应用(1)_第7张图片

链表的中间结点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
单链表的应用(1)_第8张图片
思路:(1)运用快慢指针,创建两个结构体指针,分别为slowfastslow每次走一个结点,fast每次走两个结点(如下图)
(2)返回slow指针即可单链表的应用(1)_第9张图片

struct ListNode* middleNode(struct ListNode* head) 
{
    struct ListNode* fast=head;
    struct ListNode* slow=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

单链表的应用(1)_第10张图片

你可能感兴趣的:(数据结构)