1、判断链表是否存在环型链表问题
问题:判断一个链表是否存在环,例如下面这个链表就存在环,n1-->n2-->n3-->n4-->n5-->n2,环的开始结点是n5
方法:
这里有个比较简单的解法:设两个指针p1,p2,每次循环p1向前走一步,p2向前走两步,直到p2碰到NULL指针(无环)或两个指针相等结束循环算法(有环),即如果两个指针相等则说明存在环。
代码如下:
/*节点数据结构*/
struct link{
int data;
link * next;
};
/*
*判断是否有环的方法
*
*参数来头节点的指针
*/
bool isLoop(link * head){
//p1步长为1;p2步长为2
link* p1 = head,*p2 = head;
//如果只有一个节点或两个节点,直接return false
if(head == NULL || head->next == NULL){
return false;
}
//循环前进,直到p2走到NULL或p2追上p1
do{
p1 = p1->next;
p2 = p2->next->next;
}while(p2 && p2->next && p1!=p2);
//如果有环
if(p1 == p2){
return true;
else
return false;
}
2、链表反转
问题:链表反转,比如原链表是1-->2-->3-->4-->5 通过反转后成为5-->4-->3-->2-->1
解法一:利用三个指针,当前要反转的节点的指针,当前节点之前的节点指针,当前节点之后的节点指针;反转后再向后继续遍历
代码如下:
/*节点数据结构*/
struct linka{
int data;
link * next;
};
/*
*反转
*
*参数:头节点的指针的引用
*/
bool reverse(link * &head){
//只有一个节点,即不用反转,直接返回
if(head == NULL)
return;
//定义3个辅助指针,pre指向当前要反转的节点的前一个节点;cur为当前要反转的节点;ne指向当前反转的节点的下一个节点
linka * pre,*cur,*ne;
//初始化指针
pre = head;
cur = head->next;
//循环,直到cur为NULL
while(cur){
ne = cur->next;
cur->next = pre;
pre = cur;
cur = ne;
}
//反转到最后,设置头节点指针
head->next = NULL;
head = pre;
}
代码如下:
/*节点数据结构*/
struct linka{
int data;
link * next;
};
/*
*反转
*
*参数:头节点的指针的引用
*/
linka * reverse(linka * p,link * &head){
if(p == NULL || p->next == NULL){
head = p;
return p;
}else {
linka* tmp = reverse(p->next,head);
tmp->next = p;
return p;
}
}
3、链表的合并
说明:递增有序的2个单链表合并成一个递增有序的单链表,不用任何库函数调用。
代码如下:
#include <iostream>
using namespace std;
#define move_node(a_node) do{a_node = a_node->next;}while(0)
/* 单链表节点 */
struct node{
int value;
node* next;
node()
{
value = 0;
next = NULL;
}
};
node* createList(int *l,int s)
{
node *temp = NULL;
if(s > 0)
{
node* h = new node();
h->value = l[0];
temp = h;
node *p;
for(int i = 1;i < s;++i)
{
p = new node();
p->value = l[i];
h->next = p
move_node(h);
}
}
return temp;
}
/* 遍历输出链表节点 */
void print(node* head){
node* p = head;
while ( p != NULL ){
cout << p->value << " ";
p = p->next;
}
cout << endl;
}
/* 两个有序链表进行合并 */
node* merge(node* head1, node* head2){
if(!head1)return head2;
if(!head2)return head1;
node* head,*record_head; //合并后的头指针
if (head1->value < head2->value ){
record_head = head = head1;
move_node(head1);
}else{
record_head = head = head2;
move_node(head2);
}
while (head1 && head2){
if (head1->value < head2->value ){ //如果链表1的值小于链表2的值,链表1的指针向下指
head->next = head1;
move_node(head);
move_node(head1);
}else if ( p->value == q->value ){//链表1的值等于链表2时,两链表指针都向下指
head->next = head1;
move_node(head);
head->next = head2;
move_node(head);
move_node(head1);
move_node(head2);
}else{//如果链表1的值大于链表2的值,链表2的指针向下指
head->next = head2;
move_node(head);
move_node(head2);
}
}
if (head1)head->next = head1;
else if (head2)head->next = head2;
return record_head;
}
int main(){
/* 建立有序链表A */
int a[5] = {1, 5, 8, 10, 20};
node * headA = createList(a,sizeof(a)/sizeof(a[0]));
print(headA);
/* 建立有序链表B */
int b[3] = {3, 4, 9};
node * headB = createList(b,sizeof(b)/sizeof(b[0]));
print(headB);
node *head = merge(headA, headB);
print(head);
return 0;
}