- 浏览: 95615 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
zhanglufei2010:
还有一个方法可行:直接将site-1.6.16.zip解压后的 ...
SVN与MYECLIPSE8.6
扩展问题1:查找单向链表中的倒数第k个节点。
思路:按照遍历查找链表的常用模式,可能会马上想到一种简单的方法就是:先遍历链表,看一下链表中有多少个节点。假设链表中有n个节点,那么要找倒数第k个,也就是正数n-k+1个了。接下来,只要指针从头向后走n-k步就可了。这种方法大约要执行2n-k次。
那么,有没有比上面的方法更高效的方法呢?把思维打开,不要固定在遍历链表的时候只能用有一个指针的思维定式上。我们可以尝试用多个指针以不同的次序开始遍历链表。
对于,这个问题,我们就可以设置两个指针,一个指针先在链表上走K步,然后另一个指针从链表头开始和前一个指针一起向后走,这样当第一个指针到达链表尾部时候,第二个指针就会在第一个指针前面k个结点处。这时就找到了倒数第K个节点,算法执行的次数为n 次,比上一个方法减少了一些步,如图4。
图4 查找倒数第k个节点
代码实现:
gleList* returnNodeFromBack(SingleList* head,int k)
//返回链表中的倒数第K节点的指针//输入参数:单链表的头指针,要查找的节点的倒数位置//输出参数:无//返回值:成功返回节点指针,失败返回NULLSingleList* returnNodeFromBack(SingleList* head,int k){ SingleList *firstPtr,*secondPtr; int count = 0; firstPtr = secondPtr = head; while((firstPtr)&&(count < k)) { firstPtr = firstPtr->next; count++; } if(count < k) { return NULL; } while(firstPtr) { firstPtr = firstPtr->next; secondPtr = secondPtr->next; } return secondPtr;}扩展问题2:查找单向链表中的中间节点,当节点个数为偶数时返回中间两个元素中的前者(后者)
思路:类似于第一个扩展问题,对于查找中间元素,我们首先也可以利用先遍布链表看一看总共有多少个节点,然后再走节点总个数的一半即可找到中间元素。显然,这种方法也是要遍历两次链表。
那么,能不能借鉴上面的改进方法再来改进一下这个问题呢。当然可以,在此问题中依然使用两个遍历指针。让第一个指针每次走两步,第二个指针每次走一步,这样因为第一个指针经过的节点数是第二指针的两倍,所以当第一个指针到达中点时,第二个指针正好处于链表的中间位置。
代码实现:
SingleList* returnMidNode(SingleList* head)
//返回链表的中间节点//输入参数:单链表的头指针//输出参数:无//返回值:中间节点的指针或NULLSingleList* returnMidNode(SingleList* head){ SingleList *firstPtr,*secondPtr; firstPtr = secondPtr = head; //链表中没有节点或只有一个节点 if((firstPtr == NULL) || (firstPtr->next == NULL)) { return firstPtr; } //while((firstPtr)&&(firstPtr->next)) //偶数个数时返回中间两个索引较大者 while((firstPtr->next)&&(firstPtr->next->next))//偶数个数时返回中间两个索引较小者 { firstPtr = firstPtr->next->next; secondPtr = secondPtr->next; } return secondPtr;}
扩展问题:返回两个链表的第一个交点?
仔细阅读上一个问题的思路,可发现思路中第一种解决方法就可以解决这个问题。但其时间的复杂度为O(n2)。那么能不能仿照第二种方法一样来提高算法的效率呢?答案,当然是可以。
分析两个相交链表的性质可知,如果相交,则交点之后的链表节点同时属于这两个链表。由此可以推断出,交点之后每条链表上节点的个数肯定是相同的。因此,如果两条链表节点的个数分别为len1和len2(len1>len2),那么他们的第一个交点在第一条链表上肯定是第(len1-len2)个节点之后的某个节点。
总结上面的分析,我们得出一算法:
(1)先分别遍历一遍两条链表,求出两链表各自的节点个数len1和len2。
(2)让节点多的链表先走|len1-len2|
(3)两条链表同时向后步进,并判断节点是否相同。第一个相同点就是第一个交点。
代码实现:
view sourceprint?01 //求两条单向链表的第一个交点
02 //输入参数:两个单链表的头指针
03 //输出参数:无
04 //返回值:相交返回第一个交点指针,不相交返回NULL
05 SingleList* FirstIntersectNode(SingleList *head1,SingleList *head2)
06 {
07 SingleList *firstPtr = head1,*secondPtr = head2;
08 int len1 = 0,len2 = 0;
09
10 //循环遍历第一个链表
11 while(firstPtr)
12 {
13 firstPtr = firstPtr->next;
14 len1++;
15 }
16
17 //循环遍历第二个链表
18 while(secondPtr)
19 {
20 secondPtr = secondPtr->next;
21 len2++;
22 }
23
24 firstPtr = head1;
25 secondPtr = head2;
26
27 //让指向较长链表的指针,先走出长出的几步
28 if(len1 > len2)
29 {
30 for(int i=0; i < (len1-len2);i++)
31 {
32 firstPtr = firstPtr->next;
33 }
34 }
35 else
36 {
37 for(int i=0; i < (len2-len1);i++)
38 {
39 secondPtr = secondPtr->next;
40 }
41 }
42 while(firstPtr&&secondPtr)
43 {
44 if(firstPtr == secondPtr)
45 {
46 return firstPtr;
47 }
48 firstPtr = firstPtr->next;
49 secondPtr = secondPtr->next;
50 }
51 return NULL;
52 }
思路:按照遍历查找链表的常用模式,可能会马上想到一种简单的方法就是:先遍历链表,看一下链表中有多少个节点。假设链表中有n个节点,那么要找倒数第k个,也就是正数n-k+1个了。接下来,只要指针从头向后走n-k步就可了。这种方法大约要执行2n-k次。
那么,有没有比上面的方法更高效的方法呢?把思维打开,不要固定在遍历链表的时候只能用有一个指针的思维定式上。我们可以尝试用多个指针以不同的次序开始遍历链表。
对于,这个问题,我们就可以设置两个指针,一个指针先在链表上走K步,然后另一个指针从链表头开始和前一个指针一起向后走,这样当第一个指针到达链表尾部时候,第二个指针就会在第一个指针前面k个结点处。这时就找到了倒数第K个节点,算法执行的次数为n 次,比上一个方法减少了一些步,如图4。
图4 查找倒数第k个节点
代码实现:
gleList* returnNodeFromBack(SingleList* head,int k)
//返回链表中的倒数第K节点的指针//输入参数:单链表的头指针,要查找的节点的倒数位置//输出参数:无//返回值:成功返回节点指针,失败返回NULLSingleList* returnNodeFromBack(SingleList* head,int k){ SingleList *firstPtr,*secondPtr; int count = 0; firstPtr = secondPtr = head; while((firstPtr)&&(count < k)) { firstPtr = firstPtr->next; count++; } if(count < k) { return NULL; } while(firstPtr) { firstPtr = firstPtr->next; secondPtr = secondPtr->next; } return secondPtr;}扩展问题2:查找单向链表中的中间节点,当节点个数为偶数时返回中间两个元素中的前者(后者)
思路:类似于第一个扩展问题,对于查找中间元素,我们首先也可以利用先遍布链表看一看总共有多少个节点,然后再走节点总个数的一半即可找到中间元素。显然,这种方法也是要遍历两次链表。
那么,能不能借鉴上面的改进方法再来改进一下这个问题呢。当然可以,在此问题中依然使用两个遍历指针。让第一个指针每次走两步,第二个指针每次走一步,这样因为第一个指针经过的节点数是第二指针的两倍,所以当第一个指针到达中点时,第二个指针正好处于链表的中间位置。
代码实现:
SingleList* returnMidNode(SingleList* head)
//返回链表的中间节点//输入参数:单链表的头指针//输出参数:无//返回值:中间节点的指针或NULLSingleList* returnMidNode(SingleList* head){ SingleList *firstPtr,*secondPtr; firstPtr = secondPtr = head; //链表中没有节点或只有一个节点 if((firstPtr == NULL) || (firstPtr->next == NULL)) { return firstPtr; } //while((firstPtr)&&(firstPtr->next)) //偶数个数时返回中间两个索引较大者 while((firstPtr->next)&&(firstPtr->next->next))//偶数个数时返回中间两个索引较小者 { firstPtr = firstPtr->next->next; secondPtr = secondPtr->next; } return secondPtr;}
扩展问题:返回两个链表的第一个交点?
仔细阅读上一个问题的思路,可发现思路中第一种解决方法就可以解决这个问题。但其时间的复杂度为O(n2)。那么能不能仿照第二种方法一样来提高算法的效率呢?答案,当然是可以。
分析两个相交链表的性质可知,如果相交,则交点之后的链表节点同时属于这两个链表。由此可以推断出,交点之后每条链表上节点的个数肯定是相同的。因此,如果两条链表节点的个数分别为len1和len2(len1>len2),那么他们的第一个交点在第一条链表上肯定是第(len1-len2)个节点之后的某个节点。
总结上面的分析,我们得出一算法:
(1)先分别遍历一遍两条链表,求出两链表各自的节点个数len1和len2。
(2)让节点多的链表先走|len1-len2|
(3)两条链表同时向后步进,并判断节点是否相同。第一个相同点就是第一个交点。
代码实现:
view sourceprint?01 //求两条单向链表的第一个交点
02 //输入参数:两个单链表的头指针
03 //输出参数:无
04 //返回值:相交返回第一个交点指针,不相交返回NULL
05 SingleList* FirstIntersectNode(SingleList *head1,SingleList *head2)
06 {
07 SingleList *firstPtr = head1,*secondPtr = head2;
08 int len1 = 0,len2 = 0;
09
10 //循环遍历第一个链表
11 while(firstPtr)
12 {
13 firstPtr = firstPtr->next;
14 len1++;
15 }
16
17 //循环遍历第二个链表
18 while(secondPtr)
19 {
20 secondPtr = secondPtr->next;
21 len2++;
22 }
23
24 firstPtr = head1;
25 secondPtr = head2;
26
27 //让指向较长链表的指针,先走出长出的几步
28 if(len1 > len2)
29 {
30 for(int i=0; i < (len1-len2);i++)
31 {
32 firstPtr = firstPtr->next;
33 }
34 }
35 else
36 {
37 for(int i=0; i < (len2-len1);i++)
38 {
39 secondPtr = secondPtr->next;
40 }
41 }
42 while(firstPtr&&secondPtr)
43 {
44 if(firstPtr == secondPtr)
45 {
46 return firstPtr;
47 }
48 firstPtr = firstPtr->next;
49 secondPtr = secondPtr->next;
50 }
51 return NULL;
52 }
发表评论
-
oracle 环境变量设置
2016-11-15 16:28 866转发的 http://spryingf.blog.163.co ... -
Oracle 用户锁表解决办法
2016-09-14 13:52 5031. 查看被锁的表 SELECT p.spid, ... -
Oracle 新建用户赋权
2016-07-05 17:56 631grant create session to eosccb; ... -
JSP导出excel
2016-03-14 17:54 853jsp导出excel文件并设定单元格格式 原文地址 http ... -
JS常用方法总结
2016-02-17 09:26 796function trimStr(str){ return ... -
tomcat中jndi配置
2016-02-02 15:08 580结合tomcat配置,3种配置方式 1)全局配置,tomcat ... -
maven相关
2015-10-20 20:41 1043Class "" is listed in ... -
linux相关
2015-10-13 13:47 378输入"uname -a ",可显示电脑以及 ... -
tomcat linux启动
2015-10-13 12:42 541-bash: ./startup.sh: Permission ... -
mysql命令
2015-10-09 16:43 347mysql创建数据库带指定编码: CREATE DATABAS ... -
Eclipse SVN插件离线安装
2015-09-23 16:54 4769将site-1.6.18.zip下载。 然后再eclipse ... -
mysql linux命令
2015-09-17 16:57 596比如我们要备份mysql中已经存在的名为linux的数据库,要 ... -
maven项目导入
2015-09-17 14:20 621之前自己新建过maven项目,这次是用别的项目直接使用 软件 ... -
websphere错误
2015-08-13 16:17 2327websphere Java虚拟机内存修改过大启动报错 解决 ... -
PHP STUDY
2015-07-29 10:16 568登录phpmyadmin提示: #1045 无法登录 MySQ ... -
测试要点
2015-07-27 15:01 305现在的项目有这样的问题,测试需要自己进行。在项目进行的 ... -
普元ESB学习
2015-07-24 13:54 517今天做了两个示例 1 HTTP穿透 建立公共模块,新建tr ... -
ESB 项目需求分析和方案设计浅谈(复制转载)
2015-07-24 09:09 806找到一篇非常好的文章,为了防止以后博主删除文章看不到了,所以完 ... -
第一个项目管理的总结
2015-07-23 16:41 610经历了自己第一个项目的管理和上线,有许多的不足和问题, ... -
ESB学习
2015-07-23 15:56 435百度百科的定义: ESB全称为Enterprise ...
相关推荐
在C++编程中,单向链表是一种常用的数据结构,用于存储和操作一系列有序或无序的数据元素。链表与数组不同,它不连续存储数据,而是通过节点间的指针连接,每个节点包含数据和指向下一个节点的指针。在这个场景中,...
单向链表的头部通常有一个特殊的指针(头指针),用于指向链表的第一个节点。 #### 创建单向链表 在C语言中,可以通过定义一个结构体来表示链表中的一个节点,并通过指针连接这些节点来构建链表。给定代码片段展示...
在本案例中,我们讨论的是一个单向链表的实现,这是一个基础且实用的数据结构。单向链表与双向链表不同,每个节点仅包含指向下一个节点的指针,而没有指向前一个节点的指针。 首先,让我们理解链表的基本概念。链表...
“单向链表操作详解(二)”这篇文档可能还涵盖了特殊情况的处理,例如空链表操作、错误处理以及优化链表操作的技巧等。通过详尽的实例和解释,读者可以深入理解单链表的工作原理,并学会在实际编程中灵活运用。阅读...
3. **插入和删除操作**:插入和删除节点的操作与普通单向链表类似,但需要考虑链表是否为空及插入位置的判断。 **单向循环链表常见操作** 1. **创建链表**:初始化链表,通常创建一个节点作为链表的首节点。 2. **...
在西南交通大学的这个实验中,学生需要实现对单向链表的一系列操作,包括插入、删除、查找和显示线性表的长度,以及特殊的正负数排序。 1. **插入元素**:在单向链表中插入元素需要找到目标位置的前一个节点,然后...
但如果你需要更底层的控制,比如优化空间效率或实现特殊操作,直接用指针操作链表节点可能是更好的选择。 `c++链表.txt`文件可能包含了这些链表实现的详细代码,通过学习和理解这些代码,你可以深入了解链表的工作...
链表分为单向链表和双向链表两种主要类型: 1. 单向链表:每个节点只有一个指向下一个节点的指针。 2. 双向链表:每个节点有两个指针,一个指向前一个节点,另一个指向后一个节点。 二、链表的创建 创建链表首先...
单向链表中,每个节点只有一个指向下一个节点的指针,因此只能从头到尾进行遍历。双向链表则增加了指向前一个节点的指针,允许双向遍历。 在链表的【存储结构】中,每个节点包含两个部分:数据域(data)用于存储...
单向循环链表是一种特殊的链式数据结构,它的特点是最后一个节点的指针不为NULL,而是指向链表的第一个节点(即头节点),形成一个闭合的循环。这样的设计使得从链表中的任意节点出发,都可以通过遍历找到其他所有...
根据指针的方向,链表可以分为单向链表、双向链表和循环链表。 1. **单向链表**:每个节点只有一个指针,指向下一个节点。只能从头到尾进行遍历,不能反向遍历。插入和删除操作通常比数组快,因为只需要改变相邻...
本文件聚焦于单向循环链表,它与传统的单向链表相比,主要区别在于其尾部节点的指针不是空指针,而是指向链表的第一个节点。 单向循环链表的每个节点通常包含两部分:数据域和指针域。数据域用于存储实际的数据,而...
2. **单向查找链表**:在单向链表中查找特定值的元素,需要从头节点开始遍历,逐个比较节点的值,直到找到匹配项或遍历完整个链表。这个过程的时间复杂度为O(n),其中n是链表的长度。 3. **单向环形链表**:与普通...
单向链表的每个节点只能向前指向下一个节点,而双向链表则允许节点向前和向后指。循环链表的最后一个节点会指回列表的开头,形成一个循环。 1. 插入操作: 在链表中插入新元素是一项常见的操作。对于单向链表,插入...
单向循环链表是一种特殊的线性表存储结构,其中每个节点包含一个指向下一个节点的指针,最后一个节点的指针指向链表的头节点,形成一个闭环。在约瑟夫环问题中,单向循环链表非常适合模拟游戏参与者围成一圈的情形。...
在单向链表中,每个节点只能向前指向下一个节点,而在双向链表中,每个节点可以向前也可以向后指。循环链表则是一个链表的最后一个节点指向链表的第一个节点,形成一个循环。 链表的操作包括插入、删除、查找和遍历...
根据指针的指向,链表可以分为单向链表、双向链表和循环链表。 ### 插入数据 在链表中插入数据通常涉及以下步骤: 1. 创建新节点,包含待插入的数据。 2. 找到插入位置的前一个节点。 3. 将新节点的指针指向当前...
双向链表是一种特殊类型的数据结构,与常见的单向链表相比,它具有更丰富的操作能力,可以支持前后两个方向的遍历。本篇文章将深入探讨如何创建双向链表以及其在增加和删除操作中的应用。 双向链表的每个节点不仅...
在单向链表中,每个节点只能向前指向下一个节点,而双向链表则每个节点都有前一个和后一个节点的引用,允许双向遍历。另外,环形链表是链表的一种特殊形式,其最后一个节点的指针会指向头节点,形成一个循环。 ...
单向链表是最简单的链表形式,它由多个节点组成,每个节点包含两部分:数据域和指针域。数据域用于存储实际数据,而指针域则用于存储指向下一个节点的地址。这种结构只能从前向后遍历。 在单向链表中,节点的结构...