关于链表的总结(C++循环实现)
0.目录
1.链表的基本操作
2.结点的基本操作
3.面试题
- 3.1 反转链表
- 3.2 合并两个单向排序链表
- 3.3 查找两个链表的第一个公共结点
- 3.4 删除排序链表中重复的结点
1.链表的基本操作
1.1 结点定义
#include <iostream>
using namespace std;
struct Node
{
int value;
Node* next;
};
1.2 创建链表
Node* createLinkedList(int data[], int len)
{
Node* ret = NULL;
Node* slider = NULL;
for(int i=0; i<len; i++)
{
Node* n = new Node();
n->value = data[i];
n->next = NULL;
if( slider == NULL )
{
slider = n;
ret = n;
}
else
{
slider->next = n;
slider = n;
}
}
return ret;
}
1.3 销毁链表
void destroyLinkedList(Node* list)
{
while( list )
{
Node* del = list;
list = list->next;
delete del;
}
}
1.4 打印链表
void printLinkedList(Node* list)
{
while( list )
{
cout << list->value << "->";
list = list->next;
}
cout << "NULL" << endl;
}
1.5 获取链表长度
int getListLength(Node* list)
{
int ret = 0;
while( list )
{
ret++;
list = list->next;
}
return ret;
}
测试:
int main()
{
int a[] = {1, 5, 3, 2, 4};
Node* list1 = createLinkedList(a, 5);
printLinkedList(list1);
cout << getListLength(list1) << endl;
destroyLinkedList(list1);
cout << endl;
Node* list2 = createLinkedList(NULL, 0);
printLinkedList(list2);
cout << getListLength(list2) << endl;
destroyLinkedList(list2);
cout << endl;
int b[] = {6};
Node* list3 = createLinkedList(b, 1);
printLinkedList(list3);
cout << getListLength(list3) << endl;
destroyLinkedList(list3);
return 0;
}
运行结果为:
1->5->3->2->4->NULL
5
NULL
0
6->NULL
1
2.结点的基本操作
2.1 删除结点
Node* deleteNode(Node* list, int value)
{
Node* head = list;
Node* slider = NULL;
while( head && (head->value == value) )
{
slider = head;
head = head->next;
slider = NULL;
}
Node* ret = head;
while( ret )
{
slider = ret->next;
if( slider && (slider->value == value) )
{
ret->next = slider->next;
slider = NULL;
}
else
{
ret = ret->next;
}
}
return head;
}
测试:
int main()
{
int a[] = {1, 2, 3, 2, 5};
Node* list1 = createLinkedList(a, 5);
printLinkedList(list1);
printLinkedList(deleteNode(list1, 2));
destroyLinkedList(list1);
cout << endl;
Node* list2 = createLinkedList(NULL, 0);
printLinkedList(list2);
printLinkedList(deleteNode(list2, 2));
destroyLinkedList(list2);
cout << endl;
int b[] = {2, 2, 2, 2, 2};
Node* list3 = createLinkedList(b, 5);
printLinkedList(list3);
printLinkedList(deleteNode(list3, 2));
destroyLinkedList(list3);
cout << endl;
int c[] = {1};
Node* list4 = createLinkedList(c, 1);
printLinkedList(list4);
printLinkedList(deleteNode(list4, 2));
destroyLinkedList(list4);
return 0;
}
运行结果为:
1->2->3->2->5->NULL
1->3->5->NULL
NULL
NULL
2->2->2->2->2->NULL
NULL
1->NULL
1->NULL
2.2 查找结点
Node* findNode(Node* list, int value)
{
Node* ret = NULL;
Node* slider = list;
while( slider )
{
if( slider->value == value )
{
ret = slider;
break;
}
else
{
slider = slider->next;
}
}
return ret;
}
3.面试题
3.1 反转链表
Node* reverseLinkedList(Node* list)
{
Node* ret = NULL;
Node* slider = list;
Node* next = NULL;
while( slider )
{
next = slider->next;
slider->next = ret;
ret = slider;
slider = next;
}
return ret;
}
测试:
int main()
{
int a[] = {1, 5, 3, 2, 4};
Node* list1 = createLinkedList(a, 5);
printLinkedList(list1);
printLinkedList(reverseLinkedList(list1));
destroyLinkedList(list1);
cout << endl;
Node* list2 = createLinkedList(NULL, 0);
printLinkedList(list2);
printLinkedList(reverseLinkedList(list2));
destroyLinkedList(list2);
cout << endl;
int b[] = {6};
Node* list3 = createLinkedList(b, 1);
printLinkedList(list3);
printLinkedList(reverseLinkedList(list3));
destroyLinkedList(list3);
return 0;
}
运行结果为:
1->5->3->2->4->NULL
4->2->3->5->1->NULL
NULL
NULL
6->NULL
6->NULL
3.2 合并两个单向排序链表
Node* mergeLinkedList(Node* list1, Node* list2)
{
Node* ret = NULL;
if( list1 == NULL )
{
ret = list2;
}
else if( list2 == NULL )
{
ret = list1;
}
else
{
if( list1->value < list2->value )
{
ret = list1;
list1 = list1->next;
}
else
{
ret = list2;
list2 = list2->next;
}
Node* slider = ret;
while( list1 && list2 )
{
if( list1->value < list2->value )
{
slider->next = list1;
list1 = list1->next;
}
else
{
slider->next = list2;
list2 = list2->next;
}
slider = slider->next;
}
if( list1 == NULL )
{
slider->next = list2;
}
else if( list2 == NULL )
{
slider->next = list1;
}
}
return ret;
}
测试:
int main()
{
int a[] = {1, 2, 4, 6, 8};
Node* list1 = createLinkedList(a, 5);
printLinkedList(list1);
int b[] = {2, 2, 3, 3, 7};
Node* list2 = createLinkedList(b, 5);
printLinkedList(list2);
Node* list3 = mergeLinkedList(list1, list2);
printLinkedList(list3);
destroyLinkedList(list3);
return 0;
}
运行结果为:
1->2->4->6->8->NULL
2->2->3->3->7->NULL
1->2->2->2->3->3->4->6->7->8->NULL
3.3 查找两个链表的第一个公共结点
Node* findFirstCommonNode(Node* list1, Node* list2)
{
int len1 = getListLength(list1);
int len2 = getListLength(list2);
Node* ret = NULL;
if( len1 > len2 )
{
for(int i=0; i<(len1-len2); i++)
{
list1 = list1->next;
}
}
else
{
for(int i=0; i<(len2-len1); i++)
{
list2 = list2->next;
}
}
while( list1 )
{
if( list1 == list2 )
{
ret = list1;
break;
}
else
{
list1 = list1->next;
list2 = list2->next;
}
}
return ret;
}
测试:
int main()
{
int a[] = {1, 2, 3};
Node* list1 = createLinkedList(a, 3);
int b[] = {4, 5};
Node* list2 = createLinkedList(b, 2);
int c[] = {6, 7};
Node* list3 = createLinkedList(c, 2);
Node* ret = NULL;
ret = list1;
while( ret->next )
{
ret = ret->next;
}
ret->next = list3;
ret = list2;
while( ret->next )
{
ret = ret->next;
}
ret->next = list3;
printLinkedList(list1);
printLinkedList(list2);
ret = findFirstCommonNode(list1, list2);
printLinkedList(ret);
return 0;
}
运行结果为:
1->2->3->6->7->NULL
4->5->6->7->NULL
6->7->NULL
3.4 删除排序链表中重复的结点
Node* deleteDuplicationNode(Node* list)
{
Node* head = list;
Node* toDel = NULL;
Node* end = NULL;
// 处理头结点重复的情况
while( head && head->next && (head->value == head->next->value) )
{
end = head;
// 找到最后一个与头结点重复的结点
while( end && end->next && (end->value == end->next->value) )
{
end = end->next;
}
// 删除中间与头结点重复的结点
while( head != end )
{
toDel = head;
head = head->next;
toDel = NULL;
}
// 删除最后一个与头结点重复的结点
toDel = head;
head = head->next;
toDel = NULL;
}
Node* ret = head;
Node* slider = NULL;
while( ret && ret->next )
{
slider = ret->next;
// 处理中间结点重复的情况
while( slider && slider->next && (slider->value == slider->next->value) )
{
end = slider;
// 找到最后一个与中间结点重复的结点
while( end && end->next && (end->value == end->next->value) )
{
end = end->next;
}
// 删除中间与中间结点重复的结点
while( slider != end )
{
toDel = slider;
slider = slider->next;
toDel = NULL;
}
// 删除最后一个与中间结点重复的结点
toDel = slider;
slider = slider->next;
ret->next = slider;
toDel = NULL;
}
if( ret->next == slider )
{
ret = ret->next;
}
else
{
ret->next = slider;
}
}
return head;
}
测试:
int main()
{
int a[] = {1, 1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 5};
Node* list1 = createLinkedList(a, 12);
printLinkedList(list1);
printLinkedList(deleteDuplicationNode(list1));
destroyLinkedList(list1);
cout << endl;
Node* list2 = createLinkedList(NULL, 0);
printLinkedList(list2);
printLinkedList(deleteDuplicationNode(list2));
destroyLinkedList(list2);
cout << endl;
int b[] = {2, 3, 3, 3, 4, 4, 5, 6, 6, 7};
Node* list3 = createLinkedList(b, 10);
printLinkedList(list3);
printLinkedList(deleteDuplicationNode(list3));
destroyLinkedList(list3);
cout << endl;
int c[] = {1};
Node* list4 = createLinkedList(c, 1);
printLinkedList(list4);
printLinkedList(deleteDuplicationNode(list4));
destroyLinkedList(list4);
return 0;
}
运行结果为:
1->1->1->2->2->2->3->4->4->4->5->5->NULL
3->NULL
NULL
NULL
2->3->3->3->4->4->5->6->6->7->NULL
2->5->7->NULL
1->NULL
1->NULL
关于链表的总结(C++循环实现)的更多相关文章
- Linked List Cycle 判断一个链表是否存在回路(循环)
Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using ext ...
- leetcode206 反转链表 两种做法(循环,递归)
反转链表 leetcode206 方法1 循环 public ListNode reverseList(ListNode head) { if (head == null || head.next = ...
- 剑指Offer面试题:4.从尾到头打印链表
一.题目:从尾到头打印链表 题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值. 到解决这个问题肯定要遍历链表.遍历的顺序是从头到尾的顺序,可输出的顺序却是从尾到头.也就是说第一个遍历到的结 ...
- JAVA 链表操作:循环链表
主要分析示例: 一.循环链表简述 二.单链表循环链表 三.双链表循环链表 一.循环链表简述 循环链表即链表形成了一个循环的结构,尾节点不再指向NULL,而是指向头节点HEAD,此时判定链表的结束是尾节 ...
- C语言链表各类操作详解
链表概述 链表是一种常见的重要的数据结构.它是动态地进行存储分配的一种结构.它可以根据需要开辟内存单元.链表有一个“头指针”变量,以head表示,它存放一个地址.该地址指向一个元素.链表中每一个元素称 ...
- 链表插入排序(insertion-sort-list)
自己写的代码有几个比较大的用例一直过不去,网上的代码大部分有问题,思路是先将链表置空表,再将链表中的元素循环插入到指定位置. 下面是一份正确的代码,但是是带头节点的链表: void Insertsor ...
- linux内核数据结构之链表
linux内核数据结构之链表 1.前言 最近写代码需用到链表结构,正好公共库有关于链表的.第一眼看时,觉得有点新鲜,和我之前见到的链表结构不一样,只有前驱和后继指针,而没有数据域.后来看代码注释发现该 ...
- C/C++中对链表操作的理解&&实例分析
链表概述 链表是一种常见的重要的数据结构.它是动态地进行存储分配的一种结构.它可以根据需要开辟内存单元.链表有一个“头指针”变量,以head表示,它存放一个地址.该地址指向一个元素.链表中每一个元素称 ...
- C/C++ 知识点---链表操作
1.单链表单链表的结点类型node定义: typedef struct linknode { int data; struct linknode *node; }node; <1>.建立单 ...
- 数据结构——Java实现单链表
一.分析 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.链表中的数据是以结点来表示的,每个结点由元素和指针构成.在Java中,我们可以将单链表定义成一个类,单链表的基 ...
随机推荐
- 卢卡斯定理 Lucas (p为素数)
证明摘自:(我网上唯一看得懂的证明) https://blog.csdn.net/alan_cty/article/details/54318369 结论:(显然递归实现)lucas(n,m)=luc ...
- [Jsoi2016]最佳团体 BZOJ4753 01分数规划+树形背包/dfs序
分析: 化简一下我们可以发现,suma*ans=sumb,那么我们考虑二分ans,之后做树形背包上做剪枝. 时间复杂度证明,By GXZlegend O(nklogans) 附上代码: #includ ...
- 1.4《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——编辑命令
在编辑模式中,命令行包括几个重复之前命令的功能.这些以及其他很多命令功能时常设计键盘上的特殊键,所以给出Table 1作为参考,给出了许多键在典型的Macintosh键盘上的标记符号.若你的键盘不太一 ...
- 类加载, 静态变量初始化, String不可变, 泛型使用, 内部类
1.java变量类型 java变量类型分:基本数据类型变量和Object数据类型变量,变量也是占用者内存的 例如: int i = 3; i这个变量保存的就是整形3, 占32位 Object a = ...
- [c#][福利]BTTool种子文件修改工具
前言 不知道各位看官是否有过类似的经历.好不容易找到一个电影的种子文件,想用百度云的离线下载功能去下载文件,却被百度云无情提示“离线文件因含有违规内容被系统屏蔽无法下载”!假设有这么一个场景,比如最近 ...
- 编译安装php时遇到virtual memory exhausted: Cannot allocate memory
有时候用vps建站时需要通过编译的方式来安装主机控制面板.对于大内存的VPS来说一般问题不大,但是对于小内存,比如512MB内存的godaddy VPS来说,很有可能会出现问题,因为编译过程是一个内存 ...
- 【HNOI2016】网络
题面 题解 考虑整体二分. 定义整体二分函数solve(l, r, ql, qr)表示操作权值在\([l, r]\)中,对\([ql, qr]\)的询问进行二分. 这样的话check就会很简单,先按照 ...
- libgdx学习记录25——Rectangle与Circle是否重叠
Rect与Circle重叠有三种情况: 1. Rect至少有一个角在Circle里面 2. Circle与Rect的左边或右边相交,或者Circle在Rect内 3. Circle与Rect的顶边或底 ...
- libgdx学习记录10——Particle粒子
粒子对制作画面特效很有用,可以使用Particle Editor进行自行编辑粒子效果,跟图片一起生成.p粒子文件,然后导入到程序中使用. 本文所用的粒子效果是基于其自带的demo的. 实例: pack ...
- 设计模式 笔记 享元模式 Flyweight
//---------------------------15/04/20---------------------------- //Flyweight 享元模式------对象结构型模式 /* 1 ...