当前位置: 代码网 > it编程>软件设计>数据结构 > 【数据结构初阶】单链表经典算法题十道(详解+图例)—得道飞升(上篇)

【数据结构初阶】单链表经典算法题十道(详解+图例)—得道飞升(上篇)

2024年07月31日 数据结构 我要评论
创建一个新链表,newhead,newtail 指向新链表的头结点,定义两个指针分别指向原链表的头结点,两个指针指向的数据比较大小,谁小谁尾插到新链表里面。在实例中,最后一个5结点被尾插到新链表中时,5结点的next指针指向的仍然是后面的6结点,所以最后返回的时候结果里面含有6,所以我们把最后一个等于val结点的next指针指向NULL即可!慢指针每次走一步,快指针每次走两步,当快指针走到链表的尾结点时,假设链表的长度为n,快指针走的路程是慢指针的两倍,2*慢=快,即慢指针走的路程是n/2。

目录

1、移除元素

2、反转链表

3、链表的中间节点

4、合并两个有序链表

relaxing time!!!

————————————————  天气之子·幻  ————————————————


1、移除元素

思路:

创建一个新链表(newhead,newtail),遍历原链表,把不等于 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;listnode* newtail;
    newhead=newtail=null;
    //遍历数组
    listnode* pcur=head;
    while(pcur)
    {
        if(pcur->val!=val)
        {
            //又分两种情况,链表为空,不为空
            if(newhead==null)
            {
                newtail=newhead=pcur;
            }
            else
            {
                newtail->next=pcur;
                newtail=newtail->next;
            }
        }
        pcur=pcur->next;
    }
    //[7,7,7,7,7],val=7 ,这种情况下,newtail=null,newtail->next=null,此时newtail不能解引用,所以加上if条件
    if(newtail)               
        newtail->next=null;
    return newhead;
}

注意:

当原链表为空时,newhead = newtail = pcur; 

在实例中,最后一个5结点被尾插到新链表中时,5结点的next指针指向的仍然是后面的6结点,所以最后返回的时候结果里面含有6,所以我们把最后一个等于val结点的next指针指向null即可!

2、反转链表

新奇思路:

/**
 * 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=n2->next;
    while(n2)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
        n3=n3->next;
    }
    return n1;
}

3、链表的中间节点

思路: 

奇数个结点

偶数个结点 

/**
 * definition for singly-linked list.
 * struct listnode {
 *     int val;
 *     struct listnode *next;
 * };
 */
 typedef struct listnode listnode;
struct listnode* middlenode(struct listnode* head) {
    listnode* slow=head;
    listnode* fast=head;

    //while(fast->next&&fast)错误,不可互换顺序,当为偶数个结点时,fast==null循环结束,但是while
      循环内会先判断fast->next,空指针不能解引用,会报错

    while(fast&&fast->next)
    {
        //慢指针每次走一步
        //快指针每次走两步
        slow=slow->next;
        fast=fast->next->next;
    }
    //此时slow指向的结点恰好是中间结点
    return slow;
}

快慢指针为什么可以找到中间结点?(快慢指针的原理)

慢指针每次走一步,快指针每次走两步,当快指针走到链表的尾结点时,假设链表的长度为n,快指针走的路程是慢指针的两倍,2*慢=快,即慢指针走的路程是n/2。

4、合并两个有序链表

思路:

创建一个新链表,newhead,newtail 指向新链表的头结点,定义两个指针分别指向原链表的头结点,两个指针指向的数据比较大小,谁小谁尾插到新链表里面。思路清晰,不过要注意很多细节,直接上代码:

/**
 * 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* newhead=null;
    listnode* newtail=null;

    //创建两个指针分别指向两个链表的头结点来遍历原链表
    listnode* l1=list1;
    listnode* l2=list2;
    
    while(l1&&l2)
    {
        if(l1->val<l2->val)
        {
            //l1尾插到新链表
            if(newtail==null)
            {
                newtail=newhead=l1;
            }
            else
            {
                newtail->next=l1;
                newtail=newtail->next;
            }
            l1=l1->next;
        }
        else
        {
            //l2尾插到新链表
            if(newhead==null)
            {
                newtail=newhead=l2;
            }
            else
            {
                newtail->next=l2;
                newtail=newtail->next;
            }
             l2=l2->next;
        }
    }
    //出循环,要么l1==null,要么l2==null
        if(l1)
            newtail->next=l1;  想想这里为啥不用while循环?
        if(l2)
            newtail->next=l2;
    return newhead;
}
//优化过后,申请一个不为空的链表,就无需再判断新链表是否为空,最后不要忘记free
/**
 * 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* newhead,*newtail;
     newhead=newtail=(listnode*)malloc(sizeof(listnode));
    //定义两个指针来遍历数组
    listnode* l1=list1;
    listnode* l2=list2;

    while(l1&&l2)
    {
        if(l1->val<l2->val)
        {
            newtail->next=l1;
            l1=l1->next;
            newtail=newtail->next;
        }
        else
        {
            newtail->next=l2;
            l2=l2->next;
            newtail=newtail->next;
        }
    }
    if(l1)
        newtail->next=l1;
    if(l2)
        newtail->next=l2;

    listnode* ret=newhead->next;
    free(newhead);
    newhead=null;
    return ret;
    
}


完—

relaxing time!!!

——  天气之子·幻  ——

天气之子·幻_typed_高音质在线试听_天气之子·幻歌词|歌曲下载_酷狗音乐酷狗音乐为您提供由typed演唱的高清音质无损天气之子·幻mp3在线听,听天气之子·幻,只来酷狗音乐!icon-default.png?t=n7t8https://t4.kugou.com/song.html?id=b43kh7acpv2

至此结束——

再见——

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com