链表
来源:互联网 发布:全国电子地图矢量数据 编辑:程序博客网 时间:2024/05/05 01:07
单链表
目录
1.单链表反转
2.找出单链表的倒数第4个元素
3.找出单链表的中间元素
4.删除无头单链表的一个节点
5.两个不交叉的有序链表的合并
6.有个二级单链表,其中每个元素都含有一个指向一个单链表的指针。
写程序把这个二级链表称一级单链表。
7.单链表交换任意两个元素(不包括表头)
8.判断单链表是否有环?如何找到环的“起始”点?如何知道环的长度?
9.判断两个单链表是否相交
10.两个单链表相交,计算相交点
11.用链表模拟大整数加法运算
12.单链表排序
13.删除单链表中重复的元素
这些题目在面试中经常出现,所以在这个专题中总结一下,
我所使用的代码都是C/C++。
会写一些思路,这样就不必看代码了。
冰冻三尺,非一日之寒,让我们慢慢来练习吧。
链表的节点定义如下:
- struct node
- {
- char val;
- node * next;
- };
struct node{char val;node * next;};
用结构体定义,而不是用类。
从使用的方便来说,类要更好一些,
但是为了和其他关于链表的地方保持一致还是使用了结构体来定义。
节点元素为char型,是为了输出和调试方便。
注:这些题目都是前人总结的。
总结:
1,使用指针时,一定要检查指针是否为空;
2,要考虑特殊情况,如指针为空,空链表(只有表头结点),只有一个结点等;
3,插入,删除,交换等操作时都需要使用当前结点的前驱,需要同时记录下来;
4,单链表有无环以及交叉链表求相交结点的两个题目有很大的联系,
也是经常考的题目,有些题目可以转化成这类题目;
5,递归思想很重要,在链表的倒序输出,反转,模拟大数相交,
快速排序中都有用到,分治算法往往需要用递归来做;
6,快慢指针的思想很重要,常数时间删除结点的算法也很考察智力。
题目:
顾名思义,就是反转一个单链表。
思路1:
重新开辟内存,简历一个新链表,然后从后面往前面复制。
由于单链表无法很容易得到当前节点前面的节点,所以,复制每一个节点都得从前往后找到该节点,
单个节点复制的时间复杂度为O(n),整个复杂度则为O(n^2),空间复杂度为O(n)。不可取。
思路2:
不开辟新内存,采用交换节点内容的方式。
前后两个指针,相互交换内容,之后前面的指针后移,后面的指针前移,再交换。
问题是后面指针前移的时间复杂度依然是O(n),所以时间复制度不变,仍为O(n^2)。不可取。
思路3,:
改变指针指向。时间复杂度为O(n),空间复杂度为O(1)。
注意:
输入可能为:
1,NULL
2,空链表,即只含有表头结点
3,单一结点,只有一个有效结点
4,多个结点
前三种情况都不需要处理。
反转当前结点pNode时,需要记录下一个结点pNext,且需要当前结点的上一个结点preNode。
第一个结点的反转比较特殊,初始化这些指针即可,且将第一结点的next置NULL。
结束之后,所有结点处理完了。加上表头结点即可。
注意:
有表头结点。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //1.单链表反转
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- void reverse_link(struct node * phead )
- {
- if( !phead || !phead->next || !phead->next->next )//无链表,空链表,当个节点链表则返回
- return;
- //处理第一个节点
- struct node * preNode = phead->next;
- struct node * pNode = preNode->next;
- preNode->next = NULL;
- //从第二个节点开始处理
- while(pNode)
- {
- struct node * pNext = pNode->next;
- pNode->next = preNode;
- preNode = pNode;
- pNode = pNext;
- }
- //加上表头节点
- phead->next = preNode;
- }
- void reverse_test()
- {
- string str;
- cin >> str;
- struct node *phead = create( str );
- out_link( phead );
- reverse_link( phead );
- out_link( phead );
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- reverse_test();
- return 0;
- }
// LinkTable.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <string>using namespace std;//链表的结构体struct node{char val;node * next;};//1.单链表反转struct node * create( string & str_link ){int len = str_link.length();struct node * phead = new node(); //带有表头的链表,表头中不存储任何元素struct node * preNode = phead;for( int i=0; i<len; i++ ){struct node * pNode = new node();pNode->val = str_link[i];pNode->next = NULL;preNode->next = pNode;preNode = pNode;}return phead;}void out_link( struct node * phead ){if( phead == NULL )return;struct node * pNode = phead->next;while( pNode ){cout <<pNode->val;pNode = pNode->next;}cout << endl;}void reverse_link( struct node * phead ){if( !phead || !phead->next || !phead->next->next ) //无链表,空链表,当个节点链表则返回return;//处理第一个节点struct node * preNode = phead->next;struct node * pNode = preNode->next;preNode->next = NULL;//从第二个节点开始处理while(pNode){struct node * pNext = pNode->next;pNode->next = preNode;preNode = pNode;pNode = pNext;}//加上表头节点phead->next = preNode;}void reverse_test(){string str;cin >> str;struct node *phead = create( str );out_link( phead );reverse_link( phead );out_link( phead );}int _tmain(int argc, _TCHAR* argv[]){reverse_test();return 0;}
注意:
无论采用什么思路,编程时都要考虑,链表结点个数不足4个的情况。
思路1:
先找到最后一个元素,然后再从头扫描一遍,判断该元素的之后的第三个结点是否是最后一个结点。O(4n)=O(n)。比较粗糙的方法。
思路2:
快慢指针。先让快指针先走4步,找到第四个结点。然后让快慢指针同时走,每次一步。当快指针走到最后一个结点时,慢指针指向倒数第4个元素。
思路3:
建立一个含有4个元素的循环队列(数组来模拟),扫描一遍队列,让他们不断的进入循环队列中,当最后一个结点进入循环队列后,队列的下一个元素则是倒数第4个结点。
我采用思路2来实现。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //2,找第4个结点
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- struct node * find_third_node(struct node * phead )
- {
- if( !phead ) return NULL;
- //快指针先走4步
- struct node *pFast = phead;
- struct node *pSlow = phead;
- int num =4;
- while(num--)
- {
- pFast = pFast->next;
- if(!pFast) //还没走完就没了
- {
- return NULL;
- break;
- }
- }
- //快慢指针一起走
- while(pFast)
- {
- pFast = pFast->next;
- pSlow = pSlow->next;
- }
- return pSlow;
- }
- void test()
- {
- string str;
- cin >> str;
- struct node *phead = create( str );
- cout << "The Link is : ";
- out_link( phead );
- struct node *pNode = find_third_node( phead );
- if( pNode )
- cout << "The last_third node's value is : " << pNode->val <<endl;
- else
- cout << "The number of node is less than 4." << endl;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
问题:
找出单链表的中间元素
思路:
快慢指针。
快指针每次走两步,慢指针每次走1步。快指针走到头时,慢指针所指即为中间结点。
如果结点个数N为偶数,则中间结点为第N/2个结点。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //2,找第4个结点
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- struct node * find_mid_node(struct node * phead )
- {
- if( !phead ) return NULL;
- //快慢指针
- struct node *pFast = phead;
- struct node *pSlow = phead;
- int count = 1;
- while(pFast)
- {
- pFast = pFast->next;
- if( (count++)%2 ==0 )
- pSlow = pSlow->next;
- }
- return pSlow;
- }
- void test()
- {
- string str;
- cin >> str;
- struct node *phead = create( str );
- cout << "The Link is : ";
- out_link( phead );
- struct node *pNode = find_mid_node( phead );
- if( pNode )
- cout << "The mid node's value is : " << pNode->val <<endl;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
// LinkTable.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <string>using namespace std;//链表的结构体struct node{char val;node * next;};//2,找第4个结点struct node * create( string & str_link ){int len = str_link.length();struct node * phead = new node(); //带有表头的链表,表头中不存储任何元素struct node * preNode = phead;for( int i=0; i<len; i++ ){struct node * pNode = new node();pNode->val = str_link[i];pNode->next = NULL;preNode->next = pNode;preNode = pNode;}return phead;}void out_link( struct node * phead ){if( phead == NULL )return;struct node * pNode = phead->next;while( pNode ){cout <<pNode->val;pNode = pNode->next;}cout << endl;}struct node * find_mid_node( struct node * phead ){if( !phead ) return NULL;//快慢指针struct node *pFast = phead;struct node *pSlow = phead;int count = 1;while(pFast){pFast = pFast->next;if( (count++)%2 ==0 )pSlow = pSlow->next;}return pSlow;}void test(){string str;cin >> str;struct node *phead = create( str );cout << "The Link is : ";out_link( phead );struct node *pNode = find_mid_node( phead );if( pNode )cout << "The mid node's value is : " << pNode->val <<endl;}int _tmain(int argc, _TCHAR* argv[]){test();return 0;}
问题:
一个单链表,很长,遍历一遍很慢,我们仅知道一个指向某节点的指针pNode,而我们又想删除这个节点。
思路:
将该结点的下一个结点的内容拷贝到当前结点,然后删除下一个结点。
如果该结点时最后一个结点,则必须遍历一遍单链表,找到前面一个结点,然后删掉该结点。
注意:
虽然最后一种情况是线性复杂度的,但是总体上来看还是常数时间的。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //2,找第4个结点
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- struct node * find_third_node(struct node * phead )
- {
- if( !phead ) return NULL;
- //快指针先走4步
- struct node *pFast = phead;
- struct node *pSlow = phead;
- int num =4;
- while(num--)
- {
- pFast = pFast->next;
- if(!pFast) //还没走完就没了
- {
- return NULL;
- break;
- }
- }
- //快慢指针一起走
- while(pFast)
- {
- pFast = pFast->next;
- pSlow = pSlow->next;
- }
- return pSlow;
- }
- struct node * find_last_node(struct node * phead )
- {
- struct node *pNode = phead;
- while(pNode->next)
- {
- pNode = pNode->next;
- }
- return pNode;
- }
- void delete_node(struct node * phead, struct node * pNode )
- {
- if( !phead ) return;
- //如果pNode是最后一个结点,则找到前面一个结点
- if( !pNode->next )
- {
- struct node *preNode = phead;
- while(phead)
- {
- if(preNode->next==pNode)
- break;
- else
- preNode = preNode->next;
- }
- if( !preNode )
- {
- cout <<"The node is not in the link list" << endl;
- return;
- }
- preNode->next = NULL;
- delete pNode;
- }
- else //否则拷贝下一个元素的内容,并删除下一个结点
- {
- struct node * pNext = pNode->next;
- pNode->val = pNext->val;
- pNode->next = pNext->next;
- delete pNext;
- }
- }
- void test()
- {
- string str;
- cin >> str;
- struct node *phead = create( str );
- cout << "The Link is : ";
- out_link( phead );
- struct node *pNode = find_third_node(phead);
- delete_node( phead, pNode );
- cout << "delete the last third node:" <<endl;
- out_link( phead );
- pNode = find_last_node(phead);
- delete_node( phead, pNode );
- cout << "delete last node: "<<endl;
- out_link( phead );
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
思路:
比较大小,控制指针指向,如果一个链表已经结束,则把剩下的链表加上去即可。
注意:
要判断输入时候正确。
两个链表是否为空链表等特殊情况。
如果交叉了怎么办。后面会介绍。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //2,找第4个结点
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- struct node * merge_link( struct node * phead1, struct node * phead2 )
- {
- if( !phead1 || !phead1->next)return phead2;
- if( !phead2 || !phead2->next)return phead1;
- struct node * phead = phead1;
- struct node * pNode = phead;
- struct node * pNode1 = phead1->next;
- struct node * pNode2 = phead2->next;
- delete phead2;
- while( pNode1 && pNode2)
- {
- if( pNode1->val <= pNode2->val )
- {
- pNode->next = pNode1;
- pNode1 = pNode1->next;
- }
- else
- {
- pNode->next = pNode2;
- pNode2 = pNode2->next;
- }
- pNode = pNode->next;
- }
- if( pNode2 )
- pNode->next = pNode2;
- if( pNode1 )
- pNode->next = pNode1;
- return phead;
- }
- void test()
- {
- string str;
- cin >> str;
- struct node *phead1 = create( str );
- cin >> str;
- struct node *phead2 = create( str );
- struct node * phead = merge_link( phead1, phead2 );
- cout << "after merge: "<<endl;
- out_link( phead );
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
思路:
有两种情况,相邻和不相邻。
首先找两个节点的前驱,可以通过前驱来判断是否相邻。
相邻则改变3个结点的next指针,不相邻则改变4个结点的next指针。
注意:
要判断许多出错的情况,比如,结点不在表中,结点为空,表为空等。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //建立链表
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- //输出链表
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- //找到第index个元素
- struct node * find_node(struct node* phead,int index )
- {
- if(!phead) return NULL;
- struct node * pNode = phead;
- while( index--)
- {
- pNode = pNode->next;
- if( !pNode )
- return NULL;
- }
- return pNode;
- }
- //找前驱节点
- struct node* find_preNode(struct node* phead, struct node* pNode)
- {
- if( !pNode ) return NULL;
- struct node* preNode = phead;
- while( preNode )
- {
- if( preNode->next == pNode )
- return preNode;
- preNode = preNode->next;
- }
- return NULL;
- }
- //交换节点
- void exchange_node(struct node* phead, struct node* pNode1,struct node* pNode2)
- {
- if( !phead ) return;
- //分别找到pNode1的前驱pPre1,和pNode2的前驱pPre2
- struct node* pPre1 = find_preNode( phead, pNode1);
- struct node* pPre2 = find_preNode( phead, pNode2);
- if( !pPre1 || !pPre2 )return; //有任何一个没有找到
- //相邻的情况
- struct node *pBefore, *pAfter, *pPre;
- if( pPre2 == pNode1 )
- {
- pBefore = pNode1;
- pAfter = pNode2;
- pPre = pPre1;
- }
- if( pPre1 == pNode2)
- {
- pBefore = pNode2;
- pAfter = pNode1;
- pPre = pPre2;
- }
- if( pPre2 == pNode1 || pPre1 == pNode2 )
- {
- pPre->next = pAfter;
- pBefore->next = pAfter->next;
- pAfter->next = pBefore;
- }
- else
- {
- //不相邻的情况
- struct node *pNext1 = pNode1->next;
- pNode1->next = pNode2->next;
- pPre1->next = pNode2;
- pPre2->next = pNode1;
- pNode2->next = pNext1;
- }
- }
- void test()
- {
- string str;
- cin >> str;
- struct node *phead = create( str );
- int index;
- cin >> index;
- struct node * pNode1 = find_node( phead, index );
- cin >> index;
- struct node * pNode2 = find_node( phead, index );
- exchange_node( phead, pNode1, pNode2 );
- cout << "after exchange: "<<endl;
- out_link( phead );
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
// LinkTable.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <string>using namespace std;//链表的结构体struct node{char val;node * next;};//建立链表struct node * create( string & str_link ){int len = str_link.length();struct node * phead = new node(); //带有表头的链表,表头中不存储任何元素struct node * preNode = phead;for( int i=0; i<len; i++ ){struct node * pNode = new node();pNode->val = str_link[i];pNode->next = NULL;preNode->next = pNode;preNode = pNode;}return phead;}//输出链表void out_link( struct node * phead ){if( phead == NULL )return;struct node * pNode = phead->next;while( pNode ){cout <<pNode->val;pNode = pNode->next;}cout << endl;}//找到第index个元素struct node * find_node(struct node* phead, int index ){if(!phead) return NULL;struct node * pNode = phead;while( index--){pNode = pNode->next;if( !pNode )return NULL;}return pNode;}//找前驱节点struct node* find_preNode( struct node* phead, struct node* pNode){if( !pNode ) return NULL;struct node* preNode = phead;while( preNode ){if( preNode->next == pNode )return preNode;preNode = preNode->next;}return NULL;}//交换节点void exchange_node( struct node* phead, struct node* pNode1, struct node* pNode2){if( !phead ) return;//分别找到pNode1的前驱pPre1,和pNode2的前驱pPre2struct node* pPre1 = find_preNode( phead, pNode1);struct node* pPre2 = find_preNode( phead, pNode2);if( !pPre1 || !pPre2 ) return; //有任何一个没有找到//相邻的情况struct node *pBefore, *pAfter, *pPre;if( pPre2 == pNode1 ){pBefore = pNode1;pAfter = pNode2;pPre = pPre1;}if( pPre1 == pNode2){pBefore = pNode2;pAfter = pNode1;pPre = pPre2;}if( pPre2 == pNode1 || pPre1 == pNode2 ){pPre->next = pAfter;pBefore->next = pAfter->next;pAfter->next = pBefore;}else{//不相邻的情况struct node *pNext1 = pNode1->next;pNode1->next = pNode2->next;pPre1->next = pNode2;pPre2->next = pNode1;pNode2->next = pNext1;}}void test(){string str;cin >> str;struct node *phead = create( str );int index;cin >> index;struct node * pNode1 = find_node( phead, index );cin >> index;struct node * pNode2 = find_node( phead, index );exchange_node( phead, pNode1, pNode2 );cout << "after exchange: "<<endl;out_link( phead );}int _tmain(int argc, _TCHAR* argv[]){test();return 0;}
判断单链表是否有环?
思路:
快慢指针,快指针每次走两步,慢指针每次走一步。
每次判断快指针是否到头了以及快慢指针是否指向同一元素。
快指针走到头了,则没有环;
如果快指针和慢指针指向同一个元素,则有环。
如何找到环的起始点?
思路:
如果有环,则快慢指针一定相遇在环上。
将环从快慢指针相遇结点剪开,则变成了两个单链表相交的问题。
设两个单链表的长度分别为N,M,用两个指针分别指向两链表第一个结点,
让位于长链表上的指针先走abs(N-M)步。然后一起走,相遇时则为环的起始点。
如何知道环的长度?
绕一圈即可。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //建立链表
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- //输出链表
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- //找到第index个元素
- struct node * find_node(struct node* phead,int index )
- {
- if(!phead) return NULL;
- struct node * pNode = phead;
- while( index--)
- {
- pNode = pNode->next;
- if( !pNode )
- return NULL;
- }
- return pNode;
- }
- //检查链表有无环
- //有,则返回快慢指针共同指向的点
- //无,则返回空指针
- struct node * check_loop(struct node * phead )
- {
- if(!phead)
- return NULL;
- struct node * pFast = phead;
- struct node * pSlow = phead;
- int step = 1;
- while( pFast )
- {
- pFast = pFast->next;
- if( step++%2==0 )
- {
- pSlow = pSlow->next;
- if( pSlow == pFast )
- return pSlow;
- }
- }
- return NULL;
- }
- //求两个节点的距离,即中间有多少个连线
- //返回-1为出错,如果是同一节点,则返回0
- int find_length( struct node* pNode1,struct node* pNode2 )
- {
- if(!pNode1||!pNode2) return -1;
- int len=0;
- while( pNode1 )
- {
- if( pNode1 == pNode2 )
- return len;
- pNode1 = pNode1->next;
- len++;
- }
- return -1;
- }
- //找环的起始点,pTail为快慢指针共同指向的节点
- struct node * loop_first_node(struct node * phead, struct node * pTail )
- {
- if( !phead || !pTail ) return NULL;
- struct node * pNode1 = pTail->next;
- struct node * pNode2 = phead->next;
- int M = find_length( pNode1, pTail );
- int N = find_length( pNode2, pTail );
- if( M > N )
- {
- int step = M-N;
- while(step--)
- pNode1 = pNode1->next;
- }
- if( N > M )
- {
- int step = N-M;
- while(step--)
- pNode2 = pNode2->next;
- }
- while(pNode1&&pNode2)
- {
- if(pNode1 == pNode2 )
- return pNode1;
- pNode1 = pNode1->next;
- pNode2 = pNode2->next;
- }
- return NULL;
- }
- void test()
- {
- string str;
- cin >> str;
- struct node *phead = create( str );
- int index;
- cin >> index;
- struct node * pNode1 = find_node( phead, index );
- struct node * pNode = phead;
- while( pNode->next )
- pNode = pNode->next;
- pNode->next = pNode1; //生成有环链表, 注释掉之一行则为无环链表
- struct node * pTail = check_loop( phead );
- struct node * pFirstLoopNode = NULL;
- if( pTail )
- {
- cout <<"The link has loop." <<endl;
- pFirstLoopNode = loop_first_node(phead, pTail);
- cout <<"First Loop Node is: " << pFirstLoopNode->val <<endl;
- cout <<"The number of node in loop is: " << find_length( pTail->next, pTail)+1 <<endl;
- }
- else
- cout << "The link table has no loop." <<endl;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
只介绍O(n)算法
思路1:
将链表1中各结点地址存入HashTable中,
再遍历链表2,如果有结点已经在HashTable中,则两链表相交。
思路2:
将链表1的尾结点和链表2的首结点(注意不是头结点)相连。
再判断是否有环,如果有则两链表相交。
思路3:(最简单的方法)
判断两链表的尾结点是否为同一结点,若是,则相交。
实现部分为思路2。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //建立链表
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- //输出链表
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- //找到第index个元素
- struct node * find_node(struct node* phead,int index )
- {
- if(!phead) return NULL;
- struct node * pNode = phead;
- while( index--)
- {
- pNode = pNode->next;
- if( !pNode )
- return NULL;
- }
- return pNode;
- }
- //检查链表有无环
- //有,则返回快慢指针共同指向的点
- //无,则返回空指针
- struct node * check_loop(struct node * phead )
- {
- if(!phead)
- return NULL;
- struct node * pFast = phead;
- struct node * pSlow = phead;
- int step = 1;
- while( pFast )
- {
- pFast = pFast->next;
- if( step++%2==0 )
- {
- pSlow = pSlow->next;
- if( pSlow == pFast )
- return pSlow;
- }
- }
- return NULL;
- }
- //求两个节点的距离,即中间有多少个连线
- //返回-1为出错,如果是同一节点,则返回0
- int find_length( struct node* pNode1,struct node* pNode2 )
- {
- if(!pNode1||!pNode2) return -1;
- int len=0;
- while( pNode1 )
- {
- if( pNode1 == pNode2 )
- return len;
- pNode1 = pNode1->next;
- len++;
- }
- return -1;
- }
- //找环的起始点,pTail为快慢指针共同指向的节点
- struct node * loop_first_node(struct node * phead, struct node * pTail )
- {
- if( !phead || !pTail ) return NULL;
- struct node * pNode1 = pTail->next;
- struct node * pNode2 = phead->next;
- int M = find_length( pNode1, pTail );
- int N = find_length( pNode2, pTail );
- if( M > N )
- {
- int step = M-N;
- while(step--)
- pNode1 = pNode1->next;
- }
- if( N > M )
- {
- int step = N-M;
- while(step--)
- pNode2 = pNode2->next;
- }
- while(pNode1&&pNode2)
- {
- if(pNode1 == pNode2 )
- return pNode1;
- pNode1 = pNode1->next;
- pNode2 = pNode2->next;
- }
- return NULL;
- }
- void test()
- {
- string str;
- cin >> str;
- struct node *phead1 = create( str );
- int index;
- cin >> index;
- struct node * pNode1 = find_node( phead1, index );
- cin >> str;
- struct node *phead2 = create( str );
- struct node * pNode = phead2;
- while( pNode->next )
- pNode = pNode->next;
- pNode->next = pNode1; //生成相交链表, 注释掉之一行则为不相交
- while( pNode->next ) //找到链表1的尾结点
- pNode = pNode->next;
- pNode->next = phead2->next; //连接链表2的首结点
- struct node * pTail = check_loop( phead1 );//检查是否有环
- struct node * pFirstLoopNode = NULL;
- if( pTail )
- {
- cout <<"cross." <<endl;
- }
- else
- cout << "no cross." <<endl;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
分别计算两链表的长度,为M,N。让指向长链表的指针先走,让两链表等长,
再两指针一起走,第一次相遇点即为相交点。
如果把相交链表变成一个环,则环的第一个结点即为相交点。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //建立链表
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- //输出链表
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- //找到第index个元素
- struct node * find_node(struct node* phead,int index )
- {
- if(!phead) return NULL;
- struct node * pNode = phead;
- while( index--)
- {
- pNode = pNode->next;
- if( !pNode )
- return NULL;
- }
- return pNode;
- }
- //检查链表有无环
- //有,则返回快慢指针共同指向的点
- //无,则返回空指针
- struct node * check_loop(struct node * phead )
- {
- if(!phead)
- return NULL;
- struct node * pFast = phead;
- struct node * pSlow = phead;
- int step = 1;
- while( pFast )
- {
- pFast = pFast->next;
- if( step++%2==0 )
- {
- pSlow = pSlow->next;
- if( pSlow == pFast )
- return pSlow;
- }
- }
- return NULL;
- }
- //求两个节点的距离,即中间有多少个连线
- //返回-1为出错,如果是同一节点,则返回0
- int find_length( struct node* pNode1,struct node* pNode2 )
- {
- if(!pNode1||!pNode2) return -1;
- int len=0;
- while( pNode1 )
- {
- if( pNode1 == pNode2 )
- return len;
- pNode1 = pNode1->next;
- len++;
- }
- return -1;
- }
- //找环的起始点,pTail为快慢指针共同指向的节点
- struct node * loop_first_node(struct node * phead, struct node * pTail )
- {
- if( !phead || !pTail ) return NULL;
- struct node * pNode1 = pTail->next;
- struct node * pNode2 = phead->next;
- int M = find_length( pNode1, pTail );
- int N = find_length( pNode2, pTail );
- if( M > N )
- {
- int step = M-N;
- while(step--)
- pNode1 = pNode1->next;
- }
- if( N > M )
- {
- int step = N-M;
- while(step--)
- pNode2 = pNode2->next;
- }
- while(pNode1&&pNode2)
- {
- if(pNode1 == pNode2 )
- return pNode1;
- pNode1 = pNode1->next;
- pNode2 = pNode2->next;
- }
- return NULL;
- }
- void test()
- {
- string str;
- cout << "Input the first link:"<<endl;
- cin >> str;
- struct node *phead1 = create( str );
- int index;
- cout << "Input the index of cross node: " <<endl;
- cin >> index;
- struct node * pNode1 = find_node( phead1, index );
- cout << "Input the second link:"<<endl;
- cin >> str;
- struct node *phead2 = create( str );
- struct node * pNode = phead2;
- while( pNode->next )
- pNode = pNode->next;
- pNode->next = pNode1; //生成相交链表, 注释掉这一行则为不相交
- while( pNode->next ) //找到链表1的尾结点
- pNode = pNode->next;
- pNode->next = phead2->next; //连接链表2的首结点
- struct node * pTail = check_loop( phead1 );//检查是否有环
- struct node * pFirstLoopNode = NULL;
- if( pTail )
- {
- cout <<"cross." <<endl;
- pFirstLoopNode = loop_first_node(phead1, pTail);
- cout <<"The cross node is: "<< pFirstLoopNode->val << endl;
- pNode->next = NULL; //还原,把环拆开
- }
- else
- cout << "no cross." <<endl;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
// LinkTable.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <string>using namespace std;//链表的结构体struct node{char val;node * next;};//建立链表struct node * create( string & str_link ){int len = str_link.length();struct node * phead = new node(); //带有表头的链表,表头中不存储任何元素struct node * preNode = phead;for( int i=0; i<len; i++ ){struct node * pNode = new node();pNode->val = str_link[i];pNode->next = NULL;preNode->next = pNode;preNode = pNode;}return phead;}//输出链表void out_link( struct node * phead ){if( phead == NULL )return;struct node * pNode = phead->next;while( pNode ){cout <<pNode->val;pNode = pNode->next;}cout << endl;}//找到第index个元素struct node * find_node(struct node* phead, int index ){if(!phead) return NULL;struct node * pNode = phead;while( index--){pNode = pNode->next;if( !pNode )return NULL;}return pNode;}//检查链表有无环//有,则返回快慢指针共同指向的点//无,则返回空指针struct node * check_loop( struct node * phead ){if(!phead) return NULL;struct node * pFast = phead;struct node * pSlow = phead;int step = 1;while( pFast ){pFast = pFast->next;if( step++%2==0 ){pSlow = pSlow->next;if( pSlow == pFast )return pSlow;}}return NULL;}//求两个节点的距离,即中间有多少个连线//返回-1为出错,如果是同一节点,则返回0int find_length( struct node* pNode1, struct node* pNode2 ){if(!pNode1||!pNode2) return -1;int len=0;while( pNode1 ){if( pNode1 == pNode2 )return len;pNode1 = pNode1->next;len++;}return -1;}//找环的起始点,pTail为快慢指针共同指向的节点struct node * loop_first_node( struct node * phead, struct node * pTail ){if( !phead || !pTail ) return NULL;struct node * pNode1 = pTail->next;struct node * pNode2 = phead->next;int M = find_length( pNode1, pTail );int N = find_length( pNode2, pTail );if( M > N ){int step = M-N;while(step--)pNode1 = pNode1->next;}if( N > M ){int step = N-M;while(step--)pNode2 = pNode2->next;}while(pNode1&&pNode2){if(pNode1 == pNode2 )return pNode1;pNode1 = pNode1->next;pNode2 = pNode2->next;}return NULL;}void test(){string str;cout << "Input the first link:"<<endl;cin >> str;struct node *phead1 = create( str );int index;cout << "Input the index of cross node: " <<endl;cin >> index;struct node * pNode1 = find_node( phead1, index );cout << "Input the second link:"<<endl;cin >> str;struct node *phead2 = create( str );struct node * pNode = phead2;while( pNode->next )pNode = pNode->next;pNode->next = pNode1; //生成相交链表, 注释掉这一行则为不相交while( pNode->next ) //找到链表1的尾结点pNode = pNode->next;pNode->next = phead2->next; //连接链表2的首结点struct node * pTail = check_loop( phead1 ); //检查是否有环struct node * pFirstLoopNode = NULL;if( pTail ){cout <<"cross." <<endl;pFirstLoopNode = loop_first_node(phead1, pTail);cout <<"The cross node is: "<< pFirstLoopNode->val << endl;pNode->next = NULL; //还原,把环拆开}elsecout << "no cross." <<endl;}int _tmain(int argc, _TCHAR* argv[]){test();return 0;}
例如:9->9->9->NULL
+ 1->NULL
1->0->0->0->NULL
思路:
使用递归,能够实现从前往后计算。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //建立链表
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- //输出链表
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- //求无表头链表的长度
- //返回-1为链表不存在
- int link_length( struct node* pNode )
- {
- if(!pNode) return -1;
- int len=0;
- while( pNode )
- {
- pNode = pNode->next;
- len++;
- }
- return len;
- }
- //大数相加递归算法
- //pNode1, pNode2为两个中间运算结点,但不是头结点
- struct node * add( struct node * pNode1,struct node * pNode2, int & carry )
- {
- if( !pNode1 ) return pNode2;
- if( !pNode2 ) return pNode1;
// LinkTable.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <string>using namespace std;//链表的结构体struct node{char val;node * next;};//建立链表struct node * create( string & str_link ){int len = str_link.length();struct node * phead = new node(); //带有表头的链表,表头中不存储任何元素struct node * preNode = phead;for( int i=0; i<len; i++ ){struct node * pNode = new node();pNode->val = str_link[i];pNode->next = NULL;preNode->next = pNode;preNode = pNode;}return phead;}//输出链表void out_link( struct node * phead ){if( phead == NULL )return;struct node * pNode = phead->next;while( pNode ){cout <<pNode->val;pNode = pNode->next;}cout << endl;}//求无表头链表的长度//返回-1为链表不存在int link_length( struct node* pNode ){if(!pNode) return -1;int len=0;while( pNode ){pNode = pNode->next;len++;}return len;}//大数相加递归算法//pNode1, pNode2为两个中间运算结点,但不是头结点struct node * add( struct node * pNode1, struct node * pNode2, int & carry ){if( !pNode1 ) return pNode2;if( !pNode2 ) return pNode1;
- <SPAN style="WHITE-SPACE: pre"> </SPAN>//为了参数简洁,这里增大了计算量,可以将链表长度作为参数传进来
- int len1 = link_length( pNode1 );
- int len2 = link_length( pNode2 );
- if( len1 == len2 )
- {
- if( len1==1 ) //递归终止条件
- {
- struct node * pNode = new node();
- int sum = (pNode1->val -'0' ) + ( pNode2->val -'0');
- carry = sum/10;
- pNode->val = sum%10 + '0';
- pNode->next = NULL;
- return pNode;
- }
- else
- {
- int carry_cur=0;
- struct node * pNode = new node();
- struct node * pNext = add( pNode1->next, pNode2->next, carry_cur );
- int sum = (pNode1->val - '0' ) + ( pNode2->val -'0') + carry_cur;
- carry = sum/10;
- pNode->val = sum%10 + '0';
- pNode->next = pNext;
- return pNode;
- }
- }
- if( len1>len2 )
- {
- int carry_cur=0;
- struct node * pNode =new node();
- struct node * pNext = add( pNode1->next, pNode2, carry_cur );
- int sum = (pNode1->val -'0' ) + carry_cur;
- carry = sum/10;
- pNode->val = sum%10 + '0';
- pNode->next = pNext;
- return pNode;
- }
- if( len1<len2 )
- {
- int carry_cur=0;
- struct node * pNode =new node();
- struct node * pNext = add( pNode1, pNode2->next, carry_cur );
- int sum = (pNode2->val -'0' ) + carry_cur;
- carry = sum/10;
- pNode->val = sum%10 + '0';
- pNode->next = pNext;
- return pNode;
- }
- return NULL;
- }
- struct node * add(struct node * phead1, struct node * phead2 )
- {
- if( !phead1 || !phead1->next )return phead2;
- if( !phead2 || !phead2->next )return phead1;
- int carry = 0;
- struct node * pNode = add( phead1->next, phead2->next, carry );
- if( carry > 0 ) //有进位,则需要多一个结点
- {
- struct node * pCarry =new node();
- pCarry->val = '0' + carry;
- pCarry->next = pNode;
- pNode = pCarry;
- }
- struct node * phead =new node();
- phead->next = pNode;
- return phead;
- }
- void test()
- {
- string str;
- cout << "Input the first link:"<<endl;
- cin >> str;
- struct node *phead1 = create( str );
- cout << "Input the second link:"<<endl;
- cin >> str;
- struct node *phead2 = create( str );
- struct node * phead = add( phead1, phead2);
- cout<< "The result is:" <<endl;
- out_link( phead );
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
//为了参数简洁,这里增大了计算量,可以将链表长度作为参数传进来int len1 = link_length( pNode1 );int len2 = link_length( pNode2 );if( len1 == len2 ){if( len1==1 ) //递归终止条件{struct node * pNode = new node();int sum = (pNode1->val - '0' ) + ( pNode2->val -'0');carry = sum/10;pNode->val = sum%10 + '0';pNode->next = NULL;return pNode;}else{int carry_cur=0;struct node * pNode = new node();struct node * pNext = add( pNode1->next, pNode2->next, carry_cur );int sum = (pNode1->val - '0' ) + ( pNode2->val -'0') + carry_cur;carry = sum/10;pNode->val = sum%10 + '0';pNode->next = pNext;return pNode;}}if( len1>len2 ){int carry_cur=0;struct node * pNode = new node();struct node * pNext = add( pNode1->next, pNode2, carry_cur );int sum = (pNode1->val - '0' ) + carry_cur;carry = sum/10;pNode->val = sum%10 + '0';pNode->next = pNext;return pNode;}if( len1<len2 ){int carry_cur=0;struct node * pNode = new node();struct node * pNext = add( pNode1, pNode2->next, carry_cur );int sum = (pNode2->val - '0' ) + carry_cur;carry = sum/10;pNode->val = sum%10 + '0';pNode->next = pNext;return pNode;}return NULL;}struct node * add( struct node * phead1, struct node * phead2 ){if( !phead1 || !phead1->next ) return phead2;if( !phead2 || !phead2->next ) return phead1;int carry = 0;struct node * pNode = add( phead1->next, phead2->next, carry );if( carry > 0 ) //有进位,则需要多一个结点{struct node * pCarry = new node();pCarry->val = '0' + carry;pCarry->next = pNode;pNode = pCarry;}struct node * phead = new node();phead->next = pNode;return phead;}void test(){string str;cout << "Input the first link:"<<endl;cin >> str;struct node *phead1 = create( str );cout << "Input the second link:"<<endl;cin >> str;struct node *phead2 = create( str );struct node * phead = add( phead1, phead2);cout<< "The result is:" <<endl;out_link( phead );}int _tmain(int argc, _TCHAR* argv[]){test();return 0;}
思路:
使用哈希表。
从头扫描,将出现过的节点存入哈希表中。
如果元素已经在哈希表中出现过则删除,没有则存入。
注意:
删除时需要知道前一节点。
我使用的链表中存储的是char型变量,所以哈希表即为含有256个元素的数组。
如果存储的是其他数据类型,则可以使用stl中的hash_set容器。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //建立链表
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- //输出链表
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- //去掉重复元素
- void delete_repeat_element(struct node * phead )
- {
- if( !phead || !phead->next )return;
- int * hashTable = newint[256](); //加括号是为了将hashTable中所有元素初始化为0
- struct node * pNode = phead->next;
- struct node * pPreNode = phead;
- while( pNode )
- {
- if( hashTable[pNode->val] !=0 )//说明已经出现过,该结点要删除
- {
- pPreNode->next = pNode->next;
- delete pNode; //删除结点
- pNode = pPreNode->next;
- }
- else //没有出现过,则置出现标记
- {
- hashTable[pNode->val] = 1;
- pPreNode = pNode;
- pNode = pNode->next;
- }
- }
- delete [] hashTable; //释放资源
- }
- void test()
- {
- string str;
- cout << "Input the link table :"<<endl;
- cin >> str;
- struct node *phead = create( str );
- delete_repeat_element( phead );
- cout<< "The result is:" <<endl;
- out_link( phead );
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
思路1:
将链表中的数据存入数组中,使用数组进行排序,排好后再存入链表中。
当然这并不是这题所要考察的。但是在实际应用中却相当有价值。因为链表中的排序算法都比较慢,进行转存再排序也是一种很好的方法。
思路2:
排序算法有
1, 插入排序:简单插入排序,希尔排序
2, 交换排序:冒泡排序, 快速排序
3, 选择排序:简单选择排序,堆排序
4, 归并排序
5, 基数排序
简单的排序算法有插入,冒泡,选择;
中等的有合并排序,快速排序;
复杂的有堆排序。
我实现了红色的三种排序方法。
使用链表进行排序比较繁琐,尤其是快排,需要拆分,
当然也可以多加一个指针指向要排序的队尾,这样就不用拆了。
- // LinkTable.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <string>
- using namespace std;
- //链表的结构体
- struct node
- {
- char val;
- node * next;
- };
- //建立链表
- struct node * create( string & str_link )
- {
- int len = str_link.length();
- struct node * phead =new node(); //带有表头的链表,表头中不存储任何元素
- struct node * preNode = phead;
- for( int i=0; i<len; i++ )
- {
- struct node * pNode =new node();
- pNode->val = str_link[i];
- pNode->next = NULL;
- preNode->next = pNode;
- preNode = pNode;
- }
- return phead;
- }
- //输出链表
- void out_link( struct node * phead )
- {
- if( phead == NULL )
- return;
- struct node * pNode = phead->next;
- while( pNode )
- {
- cout <<pNode->val;
- pNode = pNode->next;
- }
- cout << endl;
- }
- //找到第index个元素
- struct node * find_node(struct node* phead,int index )
- {
- if(!phead) return NULL;
- struct node * pNode = phead;
- while( index--)
- {
- pNode = pNode->next;
- if( !pNode )
- return NULL;
- }
- return pNode;
- }
- //检查链表有无环
- //有,则返回快慢指针共同指向的点
- //无,则返回空指针
- struct node * check_loop(struct node * phead )
- {
- if(!phead)
- return NULL;
- struct node * pFast = phead;
- struct node * pSlow = phead;
- int step = 1;
- while( pFast )
- {
- pFast = pFast->next;
- if( step++%2==0 )
- {
- pSlow = pSlow->next;
- if( pSlow == pFast )
- return pSlow;
- }
- }
- return NULL;
- }
- //去掉重复元素
- void delete_repeat_element( struct node * phead )
- {
- if( !phead || !phead->next ) return;
- int * hashTable =new int[256]();//加括号是为了将hashTable中所有元素初始化为0
- struct node * pNode = phead->next;
- struct node * pPreNode = phead;
- while( pNode )
- {
- if( hashTable[pNode->val] !=0 )//说明已经出现过,该结点要删除
- {
- pPreNode->next = pNode->next;
- delete pNode; //删除结点
- pNode = pPreNode->next;
- }
- else //没有出现过,则置出现标记
- {
- hashTable[pNode->val] = 1;
- pPreNode = pNode;
- pNode = pNode->next;
- }
- }
- delete [] hashTable;//释放资源
- }
- //插入排序
- void insert_sort(struct node* phead)
- {
- if( !phead || !phead->next)return;
- struct node *pCur = phead->next->next;//当前处理的结点
- struct node *pTail = phead->next;//已排好序队列的尾部结点
- while( pCur )
- {
- struct node *pNode = phead->next;//已排好序队列中与当前结点相比较的结点
- struct node *pPre = phead; //...............前一结点
- while( pNode != pCur )
- {
- if(pNode->val > pCur->val)
- break;
- pNode = pNode->next;
- pPre = pPre->next;
- }
- if( pNode == pCur ) //说明已排好序队列中没有比当前元素大的元素
- {
- pCur = pCur->next;
- pTail = pTail->next;
- }
- else //将pCur结点插入到pNode之前,即pPre之后
- {
- pTail->next = pCur->next;
- pPre->next = pCur;
- pCur->next = pNode;
- pCur = pTail->next;
- }
- }
- }
- //归并排序
- //pNode 为待排序链表的第一个元素
- //找中间结点
- struct node * find_mid_node(struct node * pNode )
- {
- if( !pNode ) return NULL;
- struct node * pFast = pNode;
- struct node * pSlow = pNode;
- int step=1;
- while( pFast->next )
- {
- pFast = pFast->next;
- if( step++%2==0 )
- pSlow = pSlow->next;
- }
- return pSlow;
- }
- //合并之后,pNode1为表头
- void merge(struct node* &pNode1,struct node* pNode2)
- {
- if( !pNode1 ) //特殊情况
- {
- pNode1 = pNode2;
- return;
- }
- if( !pNode2 ) return;
- struct node *pNode = NULL;
- struct node *phead = NULL;
- if( pNode1->val < pNode2->val )//找到表头
- {
- phead = pNode1;
- pNode1 = pNode1->next;
- }
- else
- {
- phead = pNode2;
- pNode2 = pNode2->next;
- }
- pNode = phead;
- while( pNode1 && pNode2 )
- {
- if( pNode1->val < pNode2->val)
- {
- pNode->next = pNode1;
- pNode1 = pNode1->next;
- }
- else
- {
- pNode->next = pNode2;
- pNode2= pNode2->next;
- }
- pNode = pNode->next;
- }
- if( !pNode1 )
- pNode->next = pNode2;
- else
- pNode->next = pNode1;
- pNode1 = phead;
- }
- //注意,这里的pNode是需要变的,所以用了引用,可能不太好理解
- //如果让返回值指向排行序的表头可能会好一些
- void merge_sort( struct node * &pNode )
- {
- if( !pNode || !pNode->next ) return; //递归终止条件,无结点或者只有一个结点
- struct node* pMid = find_mid_node( pNode );//分解成两半
- struct node* pNode2 = pMid->next;
- pMid->next = NULL;
- merge_sort( pNode );
- merge_sort( pNode2 );
- merge( pNode, pNode2);
- }
- //快速排序
- //划分函数
- //输入:链表头, 输出:新的链表头,选中的结点
- struct node * patition(struct node * pNode, struct node * &pSelect )
- {
- if( !pNode ) return NULL;
- struct node* phead = NULL;
- pSelect = pNode; //选中的元素,划分的依据结点,选最后一个元素
- while( pSelect->next )
- pSelect = pSelect->next;
- struct node *pScan = pNode;
- struct node *pPre = NULL; //指向pScan前一个结点
- int flag = 0;
- while( pScan != pSelect )
- {
- if( pScan->val >pSelect->val )//比选中元素大的要掉到选中元素之后
- {
- if( !pPre ) //如果是第一个
- {
- struct node *temp = pScan;
- pScan = pScan->next;
- temp->next = pSelect->next;
- pSelect->next = temp;
- }
- else //如果不是第一个
- {
- pPre->next = pScan->next;
- pScan->next = pSelect->next;
- pSelect->next = pScan;
- pScan = pPre->next;
- }
- }
- else
- {
- if( flag ==0 )
- {
- phead = pScan; //第一个小于选中的元素为表头
- flag = 1;
- }
- pPre = pScan;
- pScan = pScan->next;
- }
- }
- if( flag == 0 ) // 所有元素都比选中的大,即选中的为表头
- return pSelect;
- else
- return phead;
- }
- struct node * QuickSort( struct node * pNode )
- {
- if( !pNode || !pNode->next ) return pNode;
- struct node * pSelect=NULL;
- pNode = patition( pNode, pSelect );
- if( pSelect == pNode ) //划分后的结点为第一个结点
- {
- pSelect->next = QuickSort(pSelect->next);
- return pSelect;
- }
- else //分两个部分,pSelect前面的和后面的
- {
- struct node * pFirstTail = pNode;
- while( pFirstTail->next != pSelect )
- pFirstTail = pFirstTail->next;
- pFirstTail->next = NULL; //断开
- struct node * phead1 = QuickSort( pNode );//解决前一部分
- pFirstTail = phead1;
- while( pFirstTail->next )
- pFirstTail = pFirstTail->next;
- pFirstTail->next = pSelect; //连上
- pSelect->next = QuickSort( pSelect->next ); //解决后一部分
- return phead1;
- }
- }
- void test()
- {
- string str;
- cout << "Input the link table :"<<endl;
- cin >> str;
- struct node *phead = create( str );
- //insert_sort( phead ); //选中即为插入排序
- //merge_sort( phead->next ); //选中即为归并排序
- phead->next = QuickSort( phead->next); //选中即为快速排序
- cout<< "The result of Sort is:" <<endl;
- out_link( phead );
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- test();
- return 0;
- }
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 链表
- 13--3十进制转化为二进制
- 在Mac OS上安装配置mongoDB
- 树、图
- 电脑有点卡为什么别人的好?
- 《UNIX环境高级编程》笔记--进程组
- 链表
- HDU 2034 - 人见人爱A-B
- linux下获取CPUID,MAC地址,硬盘序列号,主板序列号
- SQL之自制LastIndexOf
- c语言中如何动态初始化二维数组
- MySQL-front
- SUSE Linux Enterprise Server 11 SP3安装详解
- weblogic静默模式启动
- IOS总结 静变量static、全局变量extern、局部变量、实例变量