吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1543|回复: 2
收起左侧

[其他转载] 【笔记】链表常见操作

[复制链接]
hack_hu 发表于 2019-3-2 20:28

链表常见类型

每一种新数据结构的出现都是为了解决原有数据结构的不足。链表的出现正是为了补充数组只能连续存储的不足。这种离散存储的方式自然携带了动态存储的特性。

单链表

单链表 是链表中最为常见的链表形式,链表中只有一个指向下一结点的指针。链表中的最后一个结点通常指向 NULL,表示链表的结束。

//Definition for singly-linked list.
 struct ListNode {
     int val;
     struct ListNode *next;
 };

单链表有一种特殊形式就是 循环链表,即最后一个结点指向头结点,整个链表形成一个环路

struct ListNode *p1,*p2,*p3;
p1->next = p2;
p2->next = p3;
p3->next = p1;

双向链表

双向链表 与单链表不同的是双向链表中存放了两个指针,pre 指向上一节点, next 指向下一结点。这种链表形式完善了单链表只能向下遍历的缺陷。

//Definition for double-linked list.
 struct ListNode {
     int val;
     struct pre *next;
     struct ListNode *next;
 };
struct ListNode *head,*p,*end; 

head->pre = NULL; head->next = p;
//头结点的上一结点指向 NULL

p->pre = head; p->next = end;
end->pre = p; end->next = NULL;
// 尾结点的下一结点指向 NULL

链表操作

链表的插入

链表的插入大致可分为两种情况,头结点插入和中间结点插入(尾结点插入与中间结点插入操作类似)

<center>头结点插入</center>

思路:让插入结点指向原头结点,指向原头结点的指针指向插入结点

struct ListNode *head,*p;
//设 head 为指向头结点的指针,p 为待插入结点

p->next = head->next;
head = p;

<center>中间结点插入</center>

思路:让插入结点指向插入点的下一结点,指向插入点指向插入结点

struct ListNode *p,*insertNode;
//设 p 为插入结点,insertNode 为待插入结点

insertNode->next = p->next;
p->next= insertNode;

链表的删除

链表的删除可以分为两种情况:

头结点删除:

struct ListNode *head;
//设 head 为指向头结点的指针

head = head->next;
// 头结点已变成下一结点,原头结点从链表中删除

中间结点删除:(尾结点删除与中间结点删除操作类似)

//设 p 为待删除结点,preNode 为待删除结点的上一节点
struct ListNode *p,*pretNode;

// 可以直接 pretNode->next = pretNode->next->next;
pretNode->next = p->next;

有序链表的合并

思路: 合并两个有序链表只需要每次找出当前结点最小值,放入归并链表中。让更小结点链表向下遍历,直至两条链表都遍历完成即完成了两个有序链表的合并

List *mergeTwoLists(List *list1, List *list2)
{
    if (!list1&&!list2) return NULL;
    //当两条链表都为遍历结束则返回 NULL

    else if (!list1) return list2;
    //因为都是有序则一条遍历结束后只要将另一条链表接在后面即可

    else if (!list2) return list1;
    else if (list1->val<list2->val)
    {
        list1->next = mergeTwoLists(list1->next, list2);
        return list1;
    }
    else
    {
        list2->next = mergeTwoLists(list1, list2->next);
        return list2;
    }
}

单链表翻转

思路: 需要有三个指针,分别指向:上一节点、当前结点、下一结点。

struct ListNode* reverseList(struct ListNode* head) {
    struct ListNode* new_head=NULL,*node=NULL;
    while (head!=NULL)
    {
        new_head = head;//新的头结点等于当前结点
        head = head->next;//当前结点变成下一结点
        new_head->next = node;//当前结点的下一结点为上一结点,从空指针开始
        node = new_head;//上一节点变成当前结点,以此循环,达到链表反转的效果
    }
    return node;
}

单链表的环路检测

思路: 通常用快慢指针来处理类似题目,快指针以慢指针两倍速遍历单链表,若快指针遍历到 NULL 则无环路,若快指针与慢指针指向同一结点,则单链表有环路。

bool hasCycle(struct ListNode *head) {
    struct ListNode *slow,*fast;
    slow=fast=head;
    while(fast&&fast->next&&fast->next->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(slow==fast)
            return true;
    }
    return false;
}

有序单链表的重复检测

思路: 因为链表是有序的,若下一结点的值与当前结点的值相等则删除该结点

struct ListNode* deleteDuplicates(struct ListNode* head) {
    struct ListNode* p = head;
        while (p&&p->next)
    {
        if (p->val == p->next->val)
            p->next=p->next->next;
        else
            p=p->next;
    }
    return head;
}

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

天才第一步 发表于 2019-3-2 21:26
有什么入门的数据结构 书吗
 楼主| hack_hu 发表于 2019-3-3 10:03
天才第一步 发表于 2019-3-2 21:26
有什么入门的数据结构 书吗

《算法》和《算法导论》是最经典的,《算法图解》是很适合入门看的。其他的可以根据语言选择,例如我 C 语言看的是 《数据结构与算法分析 C语言描述》
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 03:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表