常见的链表操作
来源:互联网 发布:阿里云客服培训中心 编辑:程序博客网 时间:2024/06/11 15:57
1. 单链表的逆序
包括逆序输出链表,三种方式,第一种是操作用栈的方式,将链表装入栈中,然后新建链表进行输出;第二种是头结点插入,没来一个节点,就插入头结点之后;第三种是对称交换,将链表以中心节点为中心,进行对称交换。
2. 合并有序链表
有序链表合并是有两种方式,一种是新建一个全新的链表,对比两个有序的链表的对应节点的大小,一次添加到新建的链表中,如果两个链表不等长,那么最后将长的那一个追加到新建链表的结尾;第二种方式与第一种方式相似,但是这种方式不新建链表,只是修改原链表的指针来进行修改,其他的与第一种方式一样
3. 判断两个单链表是否交叉,如果交叉,返回第一个交叉的节点
单链表的交叉情况,最后肯定是一个Y型的链表,也就是说,链表最后肯定是有一个公共的部分(至少为一个节点)。首先判断两个单链表的是否交叉,就是对两个链表进行遍历,看遍历的最后的节点是否相等,如果相等,那么就是交叉链表;第二步 ,就是找出第一个相交的节点,这个过程可以有两种方式:1、用长的链表减去abs(长链表-短链表),然后从短链表的头开始,从长链表的减去的对应位置开始进行链表元素的遍历比较,第一个相等的元素就是交叉链表的交点;2、将两个链表的元素全部放入两个栈中,然后比较出栈,这是相当于从链表的尾部来依次遍历两个链表,找到第一个不相等的元素,那么这个元素的前一个元素就是他们的交点;
4. 判断单链表是否有环, 如果有环则返回进入环的第一个结点
判断链表是否有环,可以设置快慢指针,例如设置指针a,b,a前进一步,b前进两部,如果b最后的元素为null,那么证明没有环,如果a==b,那么证明链表中是有环的。
如何返回第一个进入环的节点?将结点的地址做hash,遍历链表,检测是否有地址相等的结点。还有一种方式是,采用java中是set或者是hashMap结构,当第一个使该结构长度不在增加的元素出现的时候,这个元素就是进入环的第一个节点。
5. 找出单链表的中间的元素
设置快慢指针,快指针向前走两个位置,慢指针向前走一个位置,当快指针走到链表尾部的时候,慢指针正好在链表的中间;
6. 删除单链表中倒数第K个元素
设置两个指针p1和p2,p1指向链表第一个结点,p2指向第k+1个结点,两个指针同时前进,当p2到达链表尾时,p1指向倒数第k+1个结点,删除p1后面的一个结点即可。
7. 在单链表的指定节点前插入一个节点
复制一个当前节点,那么链表中现在有两个相同的相连的节点,然后用插入节点覆盖前一个节点,实现插入
8. 约瑟夫环
从题目要求中我们无法直观的感知该问题,得从一个测试用例开始。
假设0,1,2,3,4这5个数字组成一个圆圈,如果我们从数字0开始每次删除第3个数字,则删除的前四个数字是2,0,4,1,3。
这就是有名的约瑟夫环问题,它有一个简洁的数学公式,但除非我们有很深的数学素养和数学灵敏性,否则是很难一下子想出来的。
程序员最普遍的方法就是想尽一切办法让我们的代码通过测试用例。
既然是一个圆圈,我们自然就会联想到环形链表:
int LastRemaining(unsigned int n, unsigned int m){ if(n < 1 || m < 1) { return -1; } unsigned int i = 0; lisg<int> numbers; for(i = 0; i < n; ++i) { numbers.push_back(i); } list<int> :: iterator current = numbers.begin(); while(numbers.size() > 1) { for(int i = 1l i < m; ++i) { current++; if(current == numbers.end()){ current = number.begin(); } } list<int> :: iterator next = ++current; if(next == numbers.end()){ next = numbers.begin(); } --current; numbers.erase(current); current = next; } return *(current);}
我们可以用std :: list来模拟一个环形链表,但因为std :: list本身并不是一个环形结构,所以我们还要在迭代器扫描到链表末尾的时候,把迭代器移到链表的头部。 如果是使用数学公式的话,代码就会非常简单:
int LastRemaining(unsigend int n, unsigned int m){ if(n < 1 || m < 1) { return -1; } int last = 0; for(int i = 2; i <= n; ++i) { last = (last + m) % i; } return last;}
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 链表的常见操作
- 常见的链表操作
- 常见的链表操作
- 常见的链表操作
- 笔试面试常见的链表操作
- 数据结构之链表的常见操作
- java 链表的常见操作
- iOS - 私有成员变量,私有属性的写法选择
- Android开源工具项目集合转自http://blog.csdn.net/qq_16131393/article/details/51465538
- bootstrap图片剪裁预览上传
- Java语言——else if语句嵌套的优化
- app.js
- 常见的链表操作
- Socket编程(五)---NIO原理解读
- mysql索引总结----mysql 索引类型以及创建
- python学习04-序列
- React入门实践之TodoList: 添加事件和搜索框
- linux读取文件
- Android开发手记
- 开源NFV管理器 - OpenStack Tacker介绍 - 3. Tacker主要驱动作用介绍
- jquery 源码2.2.4