您的位置:首页 > 其它

合并链表,判断链表是否有环、是否相交,相交的第一个节点,进入环的第一个节点,O(1)时间复杂度删除某节点

2013-10-20 19:22 676 查看
#include<iostream>
#include<assert.h>
#include<stdlib.h>
#include<stack>
#define type char
using namespace std;
typedef struct node{
struct node *next;
type value;
}mynode;
/********************************************/
//尾插法创建列表
/********************************************/
mynode *create_node()
{
mynode *head,*pre,*p;
type x;
head=(mynode *)malloc(sizeof(mynode));
assert(head!=NULL);
head->next=NULL;
pre=head;
cout<<"输入各节点的值,以0结束:";
while(cin>>x && x!='0')
{
p=(mynode *)malloc(sizeof(mynode));
assert(p!=NULL);
p->value=x;
p->next=pre->next;
pre->next=p;
pre=p;
}
return head->next;
}
/********************************************/
//显示打印列表
/********************************************/
void print_node(mynode *head)
{
mynode *p;
cout<<"打印链表:";
p=head;
while(p)
{
cout<<p->value<<"--";
p=p->next;
}
if(p==NULL)
cout<<"^-"<<endl;
}
/*******************************************/
//已知两个单链表各自有序,把它们合并成一个链表依然有序
//已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
//先比较两个头元素,确定新链的头元素phead,此时切记phead->next=NULL,切断其与前链表的关系
//下面进行比较完,都要执行此步骤
/*******************************************/
//非递归
mynode* mergesortedlist(mynode *head1,mynode *head2)
{
if(head1==NULL)
return head2;
if(head2==NULL)
return head1;
mynode *phead,*p;
if(head1->value<head2->value)
{
phead=head1;
head1=head1->next;
}
else
{
phead=head2;
head2=head2->next;
}
phead->next=NULL;
p=phead;
while(head1 && head2)
{
if(head1->value<head2->value)
{
p->next=head1;
head1=head1->next;
}
else
{
p->next=head2;
head2=head2->next;
}
p=p->next;
p->next=NULL;
}
if(head1==NULL)
p->next=head2;
else if(head2==NULL)
p->next=head1;
cout<<"合并后链表如下:"<<endl;
return phead;
}
//递归
mynode* mergesortlist(mynode *head1,mynode *head2)
{
mynode *phead=NULL;
if(head1==NULL)
return head2;
if(head2==NULL)
return head1;
if(head1->value<head2->value)
{
phead=head1;
phead->next=mergesortlist(head1->next,head2);
}
else
{
phead=head2;
phead->next=mergesortlist(head1,head2->next);
}
return phead;
}
/****************************************/
//判断一个链表是否有环
//设定两个指针,其中一个指针走一步,另一个走两步,如果存在环,两个指针肯定相遇。
/****************************************/
void is_circle(mynode *head)
{
assert(head!=NULL);
mynode *p1,*p2;
p1=p2=head;
while(p2 && p2->next)
{
p2=p2->next->next;
p1=p1->next;
if(p1==p2)
{
cout<<"链表中存在环"<<endl;
return;
}
}
cout<<"链表中没有环"<<endl;
}
/*********************************************/
//判断两个链表是否相交
//只需要分别对两个链表遍历一边,然后判断最后一个节点是否相等即可
/*********************************************/
void is_intersect(mynode *head1,mynode *head2)
{
assert(head1!=NULL && head2!=NULL);
mynode *p1=head1;
while(p1->next)
p1=p1->next;
mynode *p2=head2;
while(p2->next)
p2=p2->next;
if(p1==p2)
cout<<"两个链表相交"<<endl;
else
cout<<"两个链表不相交"<<endl;

}
/************************************/
//求两个单链表相交的第一个节点
//首先判断两个链表是否相交,同时记录链表的长度len1,len2
//先对齐两个链表的当前节点,然后一起向后遍历
/************************************/
mynode *findfirstcommonnode(mynode *head1,mynode *head2)
{
assert(head1!=NULL && head2!=NULL);
int len1,len2;
mynode *p1,*p2;
len1=len2=1;
p1=head1;
p2=head2;
while(p1->next)
{
len1++;
p1=p1->next;
}
while(p2->next)
{
len2++;
p2=p2->next;
}
if(p1!=p2)  //先判断两个链表是否相交
{
cout<<"两个链表不相交" << endl;
return NULL;
}
mynode *p3,*p4;
int n=abs(len1-len2);
p3=head1;
p4=head2;
if(len1>len2) //两个链表的当前指针要对齐
{
while(n--)
p3=p3->next;
}
else
{
while(n--)
p4=p4->next;
}
while(p3!=p4) //一起向后遍历,相等就退出,并输出
{
p3=p3->next;
p4=p4->next;
}
return p3;
}
/***************************************/
//已知一个单链表中存在环,求进入环中的第一个节点
//首先判断是否有环,在环的一个节点处断开,形成两个相交的单链表,而这个节点作为这两个单链表的尾节点
//此时问题转化为求两个单链表相交的第一个节点
/***************************************/
mynode *findfirstnodeincircle(mynode *head)
{
assert(head!=NULL && head->next!=NULL);
mynode *p1,*p2;
p1=p2=head;
while(p2!=NULL && p2->next!=NULL)//判断是否有环
{
p1=p1->next;
p2=p2->next->next;
if(p1==p2)
break;
}
assert(p2!=NULL && p2->next!=NULL);
//形成两个相交的单链表p3、p4,它们的尾节点是ptailnode
mynode *ptailnode=p1;
mynode *p3=head;
mynode *p4=ptailnode->next;
mynode *p5=p3;
mynode *p6=p4;
int len1,len2,n;
len1=len2=0;
while(p5!=ptailnode)
{
p5=p5->next;
len1++;
}
while(p6!=ptailnode)
{
p6=p6->next;
len2++;
}
//求相交的第一个节点即满足题目要求
n=abs(len1-len2);
if(len1>len2)
{
while(n--)
p5=p5->next;
}
else{
while(n--)
p6=p6->next;
}
//对齐链表的当前节点
while(p5!=p6)
{
p5=p5->next;
p6=p6->next;
}
return p5;
}
/************************************/
//给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted
//对于删除节点,我们普通的思路就是让该节点的前一个节点指向该节点的下一个节点,
//这种情况需要遍历找到该节点的前一个节点,时间复杂度为O(n)。
//对于链表,链表中的每个节点结构都是一样的,
//所以我们可以把该节点的下一个节点的数据复制到该节点,然后删除下一个节点即可。
//要注意最后一个节点和只有一个节点的情况,这个时候只能用常见的方法来操作,
//先找到前一个节点,但总体的平均时间复杂度还是O(1)
/*************************************/

int main()
{
mynode *head1;
mynode *head2;
head1=create_node();
head2=create_node();
print_node(head1);
print_node(head2);
print_node(mergesortlist(head1,head2));
//print_node(mergesortedlist(head1,head2));
//is_circle(head1);
//is_intersect(head1,head2);
//findfirstcommonnode(head1,head2);
return 0;
}
//引自http://blog.csdn.net/luckyxiaoqiang/article/details/7393134
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐