单链表的相关操作

1.冒泡排序对单链表进行排序
void LinkListBubbleSort(LinkNode* head)
{if(head == NULL){    return;//空链表}    if(head -> next == NULL){    return;//只有一个结点}    LinkNode* cur = head;//趟数LinkNode* tail = NULL;//尾指针LinkNode* tmp = head;//次数for(; cur -> next != NULL; cur = cur -> next){    for(tmp = head; tmp -> next != tail; tmp = tmp -> next){    if(tmp -> data > tmp -> next -> data){    LinkNodeSwap(&tmp -> data, &tmp -> next -> data);}                                                                                                                                                }    tail = tmp; }    
}

    其中cur控制总共需要几趟,N个元素需要N-1趟排序, tmp控制一趟需要进行几次比较
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

2.将两个已经排好序的单链表进行合并,并且保证新链表有序
LinkNode* LinkListMerge(LinkNode* head1, LinkNode* head2)
{                                                                                                                                                            if(head1 == NULL){return head2;}if(head2 == NULL){return head1;}LinkNode* new_head;LinkListInit(&new_head);LinkNode* cur1 = head1;LinkNode* cur2 = head2;while(cur1 != NULL && cur2 != NULL){if(cur1 -> data > cur2 -> data){LinkListPushBack(&new_head, cur1 -> data);cur1 = cur1 -> next;}else{LinkListPushBack(&new_head, cur2 -> data);cur2 = cur2 -> next;}}while(cur2 != NULL){LinkListPushBack(&new_head, cur2 -> data);cur2 = cur2 -> next;}while(cur1 != NULL){LinkListPushBack(&new_head, cur1 -> data);cur1 = cur1 -> next;}return new_head;
}

    假设待排序列如下图
这里写图片描述
    那就创建一个新链表,将其初始化,每次将cur1 和 cur2 作比较,在保证 cur1 和 cur2 两个指针都不为空的前提下将它们两个中 data 小的插入到新链表的尾部就可以同时 cur1 和 cur2 往后移动,当 cur1 为空, cur2 不为空时就将 cur2 的剩下的所有元素依次全部搬到新链表中.
这里写图片描述
这里写图片描述

3.查找单链表中间结点,并且保证只能遍历一次链表

LinkNode* LinkListFindMid(LinkNode* head)
{if(head == NULL){return NULL;}if(head -> next == NULL || head -> next -> next == NULL){return head;}LinkNode* fast = head;LinkNode* slow = head;while(fast != NULL && fast -> next != NULL){fast = fast -> next -> next;slow = slow -> next;                                                                                                                                 }return slow;
}

    定义两个指针 fas t, slow ,在保证 fast 不为空并且 fast -> next 不为空的前提下,让 fast 一次走两步,slow一次走一步, 当 fast 走到 空的时候 slow 就刚好处于中间,此时返回 slow 就可以了
这里写图片描述
                这里写图片描述

4.找链表的倒数第 k 个结点
LinkNode* LinkListFindLastKNode(LinkNode* head, int K)
{if(head == NULL){return NULL;//空链表}int count = 0;LinkNode* cur = head;while(cur != NULL){count ++;cur = cur -> next;}if(K > count){return NULL;//K值大于节点个数}LinkNode* slow = head;LinkNode* fast = head;int i = 0;for(; i < K; i ++){                                                                                                                                                        if(fast != NULL){fast = fast -> next;}}while(fast != NULL){slow = slow -> next;fast = fast -> next;}return slow;
}

    同样,定义两个指针, fast 和 slow, 让 fast 先走 k 步, 然后 fas 走一步,slow跟着走一步,当 fast 等于空的时候 slow 刚好是倒数第 k 个结点
这里写图片描述
这里写图片描述
这里写图片描述
                这里写图片描述

4.删除链表的倒数第 k 个结点
void LinkListEraseLastKNode(LinkNode** phead, int K)
{if(phead == NULL){return;//非法输入}if(*phead == NULL){                                                                                                                                                        return;//空链表}int count = 0;LinkNode* cur = *phead;while(cur != NULL){count++;cur = cur -> next;}if(K > count){return;//K大于结点个数}if(K == count){LinkListPopFront(phead);return;}LinkNode* to_delete = LinkListFindLastKNode(*phead, K + 1);LinkListEraser(phead, to_delete -> next);
}

    利用前面的算法找到倒数第 k + 1个结点, 然后删除第 k + 1 个结点的下一个结点即可
这里写图片描述

5.约瑟夫环问题
LinkNode* LinkListJosephCircle(LinkNode** phead, int M)
{if(phead == NULL){                                                                                                                                                          return NULL;//非法输入}if(*phead == NULL){return NULL;//链表为空}if((*phead) -> next == *phead){return *phead;//只有一个元素}LinkNode* cur = *phead;LinkNode* to_delete;int i = 0;while(cur -> next != cur){for(i = 1; i < M; i ++){cur = cur -> next;}cur -> data = (cur -> next) -> data;to_delete = cur -> next;cur -> next = to_delete -> next;LinkNodeDestroy(&to_delete);}return cur;
}

    对于约瑟夫环问题先将这个链表形成一个带环的链表,即最后一个结点的 next 指向第一个结点,然后从第一个结点遍历这个链表,当遍历到第M个结点时就把这个结点删除,注意当给定目标是M是,指针移动M - 1次, 当指针移动M-1次时,就定义一个指针to_delete指向要删除的这个元素,然后删除这个元素,如此继续,直到剩余一个结点,即cur -> next = cur 时,就返回这个结点
             这里写图片描述

6.逆序打印单链表
void LinkListReversePrint(LinkNode* phead)
{if(phead == NULL) {return;}                                                                                                                                                           LinkListReversePrint(phead -> next);printf("%c   ", phead -> data);
}

    对于逆序打印单链表,采用递归的思想,即让指针往后遍历整个链表,直到最后一个时再将其对应的 data 打印出来即可
这里写图片描述
这里写图片描述
这里写图片描述

7.单链表的逆置
void LinkListReverse(LinkNode** phead)
{if(phead == NULL){    return;//非法输入}    if(*phead == NULL){    return;//链表为空}    if((*phead) -> next == NULL){    return;//只有一个元素}    LinkNode* cur = *phead;LinkNode* to_delete = cur; while(cur -> next != NULL){    to_delete = cur -> next;cur -> next = to_delete -> next;to_delete -> next = *phead;*phead = to_delete;                                                                                                                                    }    
}

    这里写图片描述

8.判断链表是否有环
LinkNode* LinkListHasCircle(LinkNode* head)
{if(head == NULL)                                                                                                                                           {    return NULL;//空链表}    if(head -> next == NULL){    return NULL;//一个结点并且无环}    LinkNode* fast = head;LinkNode* slow = head;while(fast != NULL && fast -> next != NULL){    fast = fast -> next -> next;slow = slow -> next;if(slow == fast){    return slow;}    }    return NULL;
}

    先构造一个有环的链表,然后定义两个指针 fast 和 slow, 在保证 fast 不为空, 以及fast -> next 不为空的前提下,fast一次走两步,slow一次走一步,如果有环,在一定时间内 fast 一定会追上 slow ,即 fast = slow,当遇到 fast 为空时,那就说明没有环
                  这里写图片描述

9.求环的长度
int LinkListGetCircleLength(LinkNode* head)
{if(head == NULL){    return 0;//空链表}    if(head -> next == NULL){    return 0;//只有一个结点,没有环}    LinkNode* meet = LinkListHasCircle(head);LinkNode* slow = meet;int size = 0; while(slow -> next != meet){    size ++;slow = slow -> next;}    return size + 1; 
}

    定义一个快指针fast,一个慢指针slow,fast一次走两步, slow一次走一步,当两者相遇时定义一个指针meet记住这个位置, 然后让slow继续往前走,同时定义一个计数器进行计数count,当slow的next等于meet时候,此时count+1便是换的长度
                 这里写图片描述

10.求环的入口点
LinkNode* LinkListGetCircleEntry(LinkNode* head)
{if(head == NULL){    return NULL;//空链表                                                                                                                                   }    if(head -> next == NULL){    return NULL;//只有一个结点,并且没有环}    LinkNode* meet = LinkListHasCircle(head);if(meet == NULL){    return NULL;}    LinkNode* slow = head;LinkNode* fast = meet;while(slow != fast){    slow = slow -> next;fast = fast -> next;}    return slow;
}

    还是快慢指针,链表开始到环入口的距离等于快慢指针相遇点到环入口的距离,即定义一个指针fast等于快慢指针相遇的那个位置,再定义一个指针slow等于head,然后两个指针一次向后遍历,当fast = slow 的之后,返回这个位置,便是环入口的位置
                    这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384109.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

socket网络编程--epoll小结

http://www.cnblogs.com/wunaozai/p/3895860.html 以前使用的用于I/O多路复用为了方便就使用select函数&#xff0c;但select这个函数是有缺陷的。因为它所支持的并发连接数是有限的(一般小于1024)&#xff0c;因为用户处理的数组是使用硬编码的。这个最大值为FD_SETSIZE&#…

进程间通信(匿名管道)

1.进程通信的目的 (1) 数据传输: 一个进程需要将它的数据传输给另一个进程     (2) 资源共享: 多个进程之间共享同样的资源     (3) 通知事件: 一个进程需要向另一个或一组进程发送消息, 通知它们发生了什么事情 2.管道 管道是一种进程之间通信的一种方式, 我们把从…

线性基入门

今天学习了神奇的线性基&#xff0c;主要是在解决异或问题时比较有用。 详细的解释和证明有大佬珠玉在前&#xff0c;如果感兴趣可以移步 补充一下自己的理解&#xff1a; 可以联系线性代数极大无关组进行理解&#xff0c;线性基就相当于异或的向量空间中的极大无关组&#xff…

单例模式及C++实现代码

http://www.cnblogs.com/cxjchen/p/3148582.html 单例模式 单例模式&#xff0c;可以说设计模式中最常应用的一种模式了&#xff0c;据说也是面试官最喜欢的题目。但是如果没有学过设计模式的人&#xff0c;可能不会想到要去应用单例模式&#xff0c;面对单例模式适用的情况&am…

UVALive - 8512——线段树维护线性基

【题目描述】 UVALive - 8512XOR 【题目分析】 这种区间线性基的问题我们可以考虑用线段树维护&#xff0c;线性基的合并的话就直接暴力合并 找到所在区间的线性基后再查找最大的数&#xff0c;我看网上的博客要说消除k的影响什么的&#xff0c;我觉得没有什么必要&#xff0c;…

命名管道

1.命名管道的创建 (1) 通过命令创建 mkfifo filename (2)在程序中创建 int mkfifo(const char* filename, mode_t mode); 2. 命名管道和匿名管道的区别 (1)匿名管道由pipe函数创建并且打开     (2)命名管道有mkfifo函数创建由open函数打开     (3) fifo 之间的两…

HYSBZ - 1101——莫比乌斯反演

【题目描述】 HYSBZ - 1101 【题目分析】 昨天测试出了一道差不多的题目&#xff0c;我只能想到暴力&#xff0c;各种优化&#xff0c;最后都是运行了好久TLE&#xff0c;最后才知道要用到莫比乌斯反演&#xff0c;就想着今天研究一下&#xff0c;得出的结论就是&#xff0c;我…

Linux下I/O多路转接之select --fd_set

http://blog.csdn.net/li_ning_/article/details/52165993 fd_set 你终于还是来了&#xff0c;能看到这个标题进来的&#xff0c;我想&#xff0c;你一定是和我遇到了一样的问题&#xff0c;一样的疑惑&#xff0c;接下来几个小时&#xff0c;我一定竭尽全力&#xff0c;写出我…

BZOJ 2844 | HYSBZ - 2844albus就是要第一个出场——线性基

【题目描述】 BZOJ 2844 | HYSBZ - 2844albus 【题目分析】 题目的意思大概是给一个数列&#xff0c;他有2n个子集&#xff0c;每个子集的元素的异或和构成新的一个数列&#xff0c;排序后问数字Q在这个序列里面的下标。 假如题目是求所有元素的异或和构成一个集合就好弄了&…

CodeForces - 641ELittle Artem and Time Machine——map+树状数组

【题目描述】 CodeForces - 641ELittle Artem and Time Machine 【题目分析】 题目的意思大概是有三种操作 1.在时间t加入一个数字x 2.在时间t删除一个数字x 3.询问在时间t集合里面x的个数 虽然题目描述很简单&#xff0c;但是t和x的范围都是109&#xff0c;我一开始想到的是主…

I/O多路转接之poll 函数

http://blog.csdn.net/li_ning_/article/details/52167224 poll 一、poll()函数&#xff1a; 这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数&#xff0c;自认为poll和select大同小异&#xff0c;下面是这个函数的声明&#xff1a; [cpp] view plaincopy …

链表相关笔试面试题

1.判断两个链表是否相交 两个链表是否相交可分为以下几种情况     &#xff08;1&#xff09;两个链表都不带环&#xff0c;此时两个链表所对应的最后一个节点是相等的     &#xff08;2&#xff09;两个链表一个带环&#xff0c;一个不带环&#xff0c;两个链表一定…

Linux经典问题—五哲学家就餐问题

http://m.blog.csdn.net/aspenstars/article/details/70149038 一、问题介绍 由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题。该问题是描述有五个哲学家共用一张圆桌&#xff0c;分别坐在周围的五张椅子上&#xff0c;在圆桌上有五…

修改之前的myshell使之支持输入输出重定向

1.open函数     这个函数是打开一个文件&#xff08;文件名叫pathname),以 flag 权限打开&#xff0c;flag 包括了以下几种 O_RDONLY&#xff08;只读&#xff09;, O_WRONLY&#xff08;只写&#xff09;, O_RDWR&#xff08;读写&#xff09;&#xff0c;当文件打开成…

HDU - 6621 K-th Closest Distance——主席树+二分

【题目描述】 HDU - 6621 K-th Closest Distance 【题目分析】 因为看到第kkk大的要求&#xff0c;刚开始的时候一直都在想怎么运用第kkk大来解决问题&#xff0c;但是后来看其他人的博客才发现并不需要用第k大&#xff0c;但是主席树维护权值线段树还是需要的&#xff0c;这…

链表相关的算法题大汇总 — 数据结构之链表奇思妙想

http://blog.csdn.net/lanxuezaipiao/article/details/22100021基本函数&#xff08;具体代码实现见后面&#xff09; 1&#xff0c;构造节点 //定义节点类型 struct Node { int value; Node*next; }; 2&#xff0c;分配节点 //之所以要分配节点原因是需要在分配函数中…

CodeForces - 372CWatching Fireworks is Fun+DP+单调队列优化

【题目描述】 CodeForces - 372CWatching Fireworks is Fun 题目的大概意思就是在一个编号为1…n的街道上现在按照时间顺序放烟花&#xff0c;每个烟花获得的幸福感为b−abs(a−x)b-abs(a-x)b−abs(a−x)&#xff0c;x为观看烟花的位置&#xff0c;为了提升我们的幸福感&#x…

双向链表的基本操作

1.双向链表的数据结构 typedef char DLinkType;typedef struct DLinkNode { DLinkType data; struct DLinkNode* next; struct DLinkNode* prev; }DLinkNode; 双向带头结点的链表有三个成员&#xff0c; 一个是数据&#xff0c; 一个是指针 next 指向当前结点的下一个结点&…

匿名管道

1.进程通信的目的 (1) 数据传输: 一个进程需要将它的数据传输给另一个进程     (2) 资源共享: 多个进程之间共享同样的资源     (3) 通知事件: 一个进程需要向另一个或一组进程发送消息, 通知它们发生了什么事情 2.管道 管道是一种进程之间通信的一种方式, 我们把从…

Currency Exchange——最短路Bellman-Ford算法

【题目描述】 Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the sam…