链表高级算法——2

一、判断两个链表是否相交

int CheckCross(pLinkList list1, pLinkList list2)   //判断链表是否相交
{
	assert(list1);
	assert(list2);
	pLinkNode cur1 = list1->pHead;
	pLinkNode cur2 = list2->pHead;
	if ((NULL==list1->pHead)||(NULL==list2->pHead))
	{
		return -1;
	}
	while (NULL!=cur1->next)
	{
		cur1 = cur1->next;
	}
	while(NULL!=cur2->next)
	{
		cur2 = cur2->next;
	}
	if (cur1 == cur2)
	{
		return  1;                //相交
	}
	else
	{
		return -1;                 //不相交
	}
}

二、合并两个有序链表

合并两个有序链表的方法很多,下面介绍一种最常见的方法!!!

算法:

首先创建一个虚拟头结点,将两个链表看做两个有序集合,每次从这两个集合里面分别取出第一个结点进行比较,把较小值从集合中剥离出来链接到虚拟结点之后,再用一个指针last记录虚拟结点这条链表的末尾,如此反复进行,直到其中一个集合为空,再将另一个集合中的所有结点链接到last之后。

pLinkList Merge(pLinkList list1, pLinkList list2)    //合并两个有序链表
{
	assert(list1);
	assert(list2);
	if ((NULL == list1->pHead)&&(NULL == list2->pHead))   //考虑特殊情况
	{
		return NULL;
	}
	else if (NULL == list1->pHead)
	{
		return list2;
	}
	else if(NULL == list2->pHead)
	{
		return list1;
	}
	pLinkNode last = NULL;
	pLinkNode newHead = NULL;                       //虚拟头结点
	if (list1->pHead->data <list2->pHead->data)     //把对第一个结点特殊处理
	{
		newHead= list1->pHead;
		list1->pHead = list1->pHead->next;
	}
	else
	{
		newHead = list2->pHead;
		list2->pHead = list2->pHead->next;
	}
	last=newHead;                                    //让last指向虚拟结点链表的尾部
	while ((NULL!= list1->pHead)&&(NULL!= list2->pHead))
	{
		if (list1->pHead->data <list2->pHead->data)
		{
			last->next = list1->pHead;
			list1->pHead = list1->pHead->next;
		}
		else
		{
			last ->next= list2->pHead;
			list2->pHead = list2->pHead->next;
		}
		last = last->next;
	}
	if (NULL == list1->pHead)                 //将集合中剩下的元素链接到last之后
	{
		last->next = list2->pHead;
	}
	else
	{
		last->next = list1->pHead;
	}
	list1->pHead = newHead;
	return list1;
}

三、判断一个链表是否带环,若带环返回相遇点的位置

这个问题需要应用到快慢指针才能解决,快指针fast每次走两步,慢指针每次走一步。因为fast每次都要比slow多走一步,如果链表带环,则最终fast一定会和slow相遇。

pLinkNode CheckCycle(pLinkList list)             //判断是否带环,若带环则返回相遇位置
{
	assert(list);
	pLinkNode fast = list->pHead;                 //快指针
	pLinkNode slow = list->pHead;                 //慢指针
	if (NULL==list->pHead)
	{
		return NULL;
	}
	while (fast!= NULL)
	{
		if (NULL != fast->next)
		{
			fast = fast->next->next;
			slow = slow->next;
		}
		else
		{
			break;
		}
		if (fast == slow)                   //快慢指针相遇则有环
		{
			return slow;
		}
	}
	return NULL;                            //没环则返回NULL
}

四、求带环链表中环的长度

这个问题比较简单,第三题中已经找到了快慢指针在环中的相遇点,我们只需要再设置一个count,从这个相遇点出发遍历一遍环就行了。

int  GetCircleLength(pLinkNode meet)         //若链表带环这返回环的长度
{
	assert(meet);
	pLinkNode cur = meet->next;
	int count = 1;
	while (cur!=meet)
	{
		count++;
		cur = cur->next;
	}
	return count;
}

五、求带环链表中环的入口点

针对这个问题我们有一个定理,用两个指针,分别从链表的头和环中的相遇点出发,经过若干步之后这两个指针会在环的入口处相遇。

pLinkNode GetCycleEntryNode(pLinkList list, pLinkNode meet)   //查找环的入口
{
	assert(list);
	pLinkNode link = list->pHead;             //link指向链表的头
	pLinkNode cycle = meet;                   //cycle指向链表的相遇点
	while (link != cycle)
	{
		link = link->next;
		cycle = cycle->next;
	}
	return link;
}

时间: 2024-10-09 04:55:46

链表高级算法——2的相关文章

链表高级算法--1

一.链表选择排序 void SelectSort(pLinkList list) //选择排序 { assert(list); if (NULL == list->pHead || NULL ==list->pHead->next) //如果是空链表或者只有一个结点则直接结束 { return; } pLinkNode cur = list->pHead; pLinkNode p = NULL; pLinkNode min = NULL; while (cur!=NULL) { p

集合框架之链表集合算法

链表集合算法: 1.链=引用 2.链表集合与数组集合的区别:在增值方面,数组集合的速度比链表集合算法[学Java,到凯哥学堂kaige123.com]的速度要快:但是链表集合在增删值和修改值方面要更灵活,它的原理就好比链条. 3.链表的分类: 3.1单链集合(了解即可):上家能找到下家,但是下家找不到上家,即通过上一个数组可以找到下一个数组,但是没办法通过下一个数组找到上一个数组.如下图: 3.2双链集合:上家能找到下家,下家也能找到上家.如下图: 4.代码实现(以双链为例): 4.1添加值 4

链表创建和链表遍历算法的演示_C语言

今天搞了一个多小时,头是疼的,应该是没休息好吧,学习了数据结构这一节,感觉收益良多,下面贴上代码和心得: 1 /*24_链表创建和链表遍历算法的演示*/ 2 # include <stdio.h> 3 # include <malloc.h> 4 # include <stdlib.h> 5 6 typedef struct Node 7 { 8 int data;//数据域 9 struct Node * pNext;//指针域 10 }NODE, *PNODE;//

单向链表反转算法——递归版和迭代版

最近在做笔试题时,遇到一道编程题:单向链表反转算法.一时紧张,没写出来就提前交卷了,然而交完卷就想出来了... 最初想出来的是递归版,遗憾的是没能做到尾递归,后来又琢磨出了迭代版.后来用实际编译运行测试了一遍,能正常运行. 递归版的灵感来源于<Haskell 趣学指南>中非常简洁的快速排序算法的实现,其思想是将单向链表分割头部和尾部.其中头部指是链表的第一个节点,尾部是指除去第一个节点后的子链表.通过递归的方法,将子链表继续分割成头部和尾部,直至尾部指剩下一个节点,无法继续分割,然后将头部和尾

面试高级算法梳理笔记

面试高级算法梳理笔记 1.1 说明 本篇为<挑战程序设计竞赛(第2版)>读书笔记系列,旨在: 梳理算法逻辑 探索优化思路 深入代码细节 1.2 目录 原文首发于个人博客Jennica.Space,按算法难度划分为初中高三个级别,详细目录及链接如下: 初级篇 穷竭搜索 贪心 动态规划 数据结构 图论 数论 中级篇 二分搜索 常用技巧 数据结构(二) 动态规划(二) 网络流 计算几何 高级篇 数论(二) 博弈论 图论(二) 常用技巧(二) 智慧搜索 分治 字符串 1.3 题解 配套习题及详解同步发

Freecodecamp 高级算法(个人向)

freecodecamp 高级算法地址戳这里. freecodecamp的初级和中级算法,基本给个思路就能完成,而高级算法稍微麻烦了一点,所以我会把自己的解答思路写清楚,如果有错误或者更好的解法,欢迎留言. Validate US Telephone Numbers 如果传入字符串是一个有效的美国电话号码,则返回 true. 简单来说,美国号码的规则就是,国家代码(必须为1),然后就是3,3,4的数字组合,前三个数字可以用括号包起来.另外就是间隔使用空格或者"-". 因为输入值肯定是字

【高级算法】禁忌搜索算法解决3SAT问题(C++实现)

转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46440389 近期梳理,翻出了当年高级算法课程做的题目.禁忌搜索算法解决3SAT问题. 吐槽:数学符号怎样在编辑器里打出来啊,为了保留符号,我直接截图了. 1 SAT问题描写叙述 定理4.4.1: 赋值v为使CNF可满足的充要条件是f(x1,x2,-,xm)达到最小值0. 2  禁忌搜索算法 禁忌搜索算法是在局部搜索的过程中引进了贪心选择机制.并利用禁忌表改动邻域,通过构造的候选

链表插入和删除,判断链表是否为空,求链表长度算法的,链表排序算法演示——C语言描述

关于数据结构等的学习,以及学习算法的感想感悟,听了郝斌老师的数据结构课程,其中他也提到了学习数据结构的或者算法的一些个人见解,我觉的很好,对我的帮助也是很大,算法本就是令人头疼的问题,因为自己并没有学习过算法的系统性的课程,现在还是处于不断摸索的阶段,好多算法题目根本就没有什么思路,导致自己对好多题目都很是头疼,就算是自己做过的一些算法的题目,再次遇到也还是不一定会做出来,他给出的建议就是,看懂别人的程序,然后自己去敲,一定会出错,然后调试,有错误接着调试,一直到没有错误为止,并且要时常的去复习

js 高级算法 - 动态规划

主要是看了<数据结构与算法>有所感悟,虽然这本书被挺多人诟病的,说这有漏洞那有漏洞,但并不妨碍我们从中学习知识. 其实像在我们前端的开发中,用到的高级算法并不多,大部分情况if语句,for语句,swith语句等等,就可以解决了.稍微复杂的,可能会想到用递归去的解决. 但要注意的是递归写起来简洁,但实际上执行的效率并不高. 我们再看看动态规划的算法: 动态规划解决方案从底部开始解决问题, 将所有小问题解决掉, 然后合并成一个整体解决方案, 从而解决掉整个大问题 . 实例举例  (计算斐波那契数列