判斷鏈表相交,刪除無頭單鏈表的非尾節點及倒序打印單鏈表——題集(四)

判斷鏈表相交,刪除無頭單鏈表的非尾節點及倒序打印單鏈表——題集(四)

       博主昨天懶丟了,耽擱了昨天的題集更新,所以今天的題集分享可能有點長,首先判斷鏈表相交併求交點的情況,其次刪除無頭單鏈表的非尾節點倒序打印單鏈表

       在鏈表帶環不帶環的情況下,分別判斷兩個鏈表是否相交,若相交,求交點。

源代碼如下:

#include<iostream>
using namespace std;
#include<stack>
 
struct ListNode{
int val;
ListNode* next;
ListNode(int _val)
:val(_val)
,next(NULL)
{}
};
 
//判斷兩個鏈表是否相交,若相交,求交點。(鏈表不帶環)
bool intersect(ListNode* l1, ListNode* l2, ListNode*& met){//鏈表不帶環若相交,求交點
if(l1==	NULL || l2== NULL)return false;
stack<ListNode*> s1;
stack<ListNode*> s2;
//全部放入棧中
while(l1->next != NULL){
s1.push(l1);
l1=l1->next;
}
s1.push(l1);//別忘了最後一個元素
while(l2->next !=NULL){
s2.push(l2);
l2=l2->next;
}
s2.push(l2);//別忘了最後一個元素
 
while(!s1.empty() && !s2.empty() && s1.top() == s2.top()){
met=s1.top();
s1.pop();
s2.pop();
}
if(met==NULL){
return false;
}
return true;
}
 
//判斷鏈表是否帶環,並用met帶出相遇點;前一篇博客中有,哎,我還是粘一下吧。
bool Isloop(ListNode* l1,ListNode*& met){
ListNode* fast=l1;
ListNode* low=l1;
 
do{
int i=0;
while(i<2){//fast走兩步,low走一步,後再判斷是否相等。
if(fast->next != NULL){
fast=fast->next;
i++;
}
else{
return false;
}
}
low=low->next;
}while(fast != low);
met=fast;
return true;
}
 
//判斷兩個鏈表是否相交,若相交,求交點。(鏈表帶環)
bool intersect2(ListNode* l1, ListNode* l2, ListNode*& met1, ListNode*& met2){//鏈表帶環若相交,求交點
stack<ListNode*> s1;
stack<ListNode*> s2;
while(l1->next !=NULL){
s1.push(l1);
if(l1==met1) break;
l1=l1->next;
}
if(l1->next ==NULL)return false;
 
int num=0;
while(l2->next !=NULL){
s2.push(l2);
if(l2==met1) break;
if(l2==met2){
num++;
if( num > 1) break;//循環一遍還是沒有找到切入點,兩個鏈表就不可能相交了
}
l2=l2->next;
}
if(l2->next ==NULL || num > 1)return false;
 
while(!s1.empty() && !s2.empty() && s1.top() == s2.top()){
met1=s1.top();
s1.pop();
s2.pop();
}
 
return true;
}
 
void test(ListNode* lA1, ListNode* lB1){//判斷相交的一系列操作
ListNode* met1=NULL;
ListNode* met2=NULL;
bool P1=Isloop( lA1, met1);
bool P2=Isloop( lB1, met2);
if(!P1 && !P2)//兩鏈表都不帶環//判斷鏈表是否帶環
{
//met1=NULL;
if(intersect(lA1, lB1, met1))//鏈表不帶環,若相交,求交點
{
cout<<"兩鏈表都不帶環,且相交,交點爲:"<<met1->val<<endl;
}
else{
cout<<"兩鏈表都不帶環,且不相交"<<endl;
}
}
else if(P1 && P2){//兩鏈表都帶環//判斷鏈表是否帶環
if(intersect2(lA1, lB1, met1, met2))//鏈表帶環,若相交,求交點
{
cout<<"兩鏈表都帶環,且相交,交點爲:"<<met1->val<<endl;
}
else{
cout<<"兩鏈表都帶環,且不相交"<<endl;
}
}
else{
cout<<"兩鏈表不相交"<<endl;
}
}
 
void Testinters(){//判斷兩個鏈表是否相交,若相交,求交點,分別考慮帶環和不帶環的情況
ListNode lA1(1);
ListNode lA2(2);
ListNode lA3(3);
ListNode lA4(4);
ListNode lA5(11);
 
lA1.next = &lA2;
lA2.next = &lA3;
lA3.next = &lA4;
lA4.next = &lA5;
 
 
ListNode lB1(7);
ListNode lB2(3);
ListNode lB3(8);
ListNode lB4(4);
ListNode lB5(11);
 
lB1.next = &lB2;
lB2.next = &lB3;
lB3.next = &lB4;
lB4.next = &lB5;
lB5.next = &lB2;
 
ListNode lC1(7);
ListNode lC2(3);
ListNode lC3(8);
ListNode lC4(4);
ListNode lC5(11);
 
lC1.next = &lC2;
lC2.next = &lC3;
lC3.next = &lC4;
lC4.next = &lC5;
lC5.next = &lC2;
 
 
cout<<"test(&lA1, &lB1): ";
test(&lA1, &lB1);
cout<<"test(&lA1, &lA2): ";
test(&lA1, &lA2);
cout<<"test(&lB1, &lB3): ";
test(&lB1, &lB3);
cout<<"test(&lB1, &lB5): ";
test(&lB1, &lB5);
cout<<"test(&lB1, &lC5): ";
test(&lB1, &lC5);
cout<<"test(&lB1, &lC1): ";
test(&lB1, &lC1);
 
}
 
int main(){
Testinters();//判斷兩個鏈表是否相交,若相交,求交點,分別考慮帶環和不帶環的情況
system("pause");
return 0;
}

運行界面及詳解

 

刪除無頭單鏈表的非尾節點倒序打印單鏈表的源代碼和運行界面。

源代碼如下:

#include<iostream>
using namespace std;
 
struct ListNode{
int val;
ListNode* next;
ListNode(int _val)
:val(_val)
,next(NULL)
{}
};
 
bool DeleteP(ListNode* del){//刪除非尾結點
if(del->next == NULL){
cout<<"要刪除的結點爲尾結點,不符合要求"<<endl;
return false;
}
//在頭,在中間——替換
ListNode* next = del->next;
 
del->val = next->val;
del->next = next->next;
 
//結構體沒有析構,不用手動刪除next結點;
return true;
}
 
 
//從頭到尾打印單鏈表
void Printf(ListNode* l1){//打印
while(l1!=NULL){
cout<<l1->val<<" ";
l1=l1->next;
}
printf("\n");
}
 
//從尾到頭打印單鏈表
void ReversePrint(ListNode* l1){//逆序打印
if(l1->next != NULL)
ReversePrint(l1->next);
cout<<l1->val<<" ";
}
 
void TestPrint(){
ListNode l1(1);
ListNode l2(2);
ListNode l3(3);
ListNode l4(4);
ListNode l5(11);
 
l1.next = &l2;
l2.next = &l3;
l3.next = &l4;
l4.next = &l5;
 
cout<<"正序打印單鏈表: ";
Printf(&l1);//正序打印單鏈表
cout<<"逆序打印單鏈表: ";
ReversePrint(&l1);//逆序打印單鏈表
cout<<"\n\n";
 
 
cout<<"DeleteP(&l5): ";
DeleteP(&l5);//刪除非尾結點
cout<<"正序打印單鏈表: ";
Printf(&l1);//正序打印單鏈表
cout<<"逆序打印單鏈表: ";
ReversePrint(&l1);//逆序打印單鏈表
cout<<"\n\n";
cout<<"DeleteP(&l3): ";
DeleteP(&l3);//刪除非尾結點
cout<<"正序打印單鏈表: ";
Printf(&l1);//正序打印單鏈表
cout<<"逆序打印單鏈表: ";
ReversePrint(&l1);//逆序打印單鏈表
cout<<"\n\n";
 
cout<<"DeleteP(&l1): ";
DeleteP(&l1);//刪除非尾結點
cout<<"正序打印單鏈表: ";
Printf(&l1);//正序打印單鏈表
cout<<"逆序打印單鏈表: ";
ReversePrint(&l1);//逆序打印單鏈表
cout<<"\n\n";
}
 
int main(){
TestPrint();//從尾到頭打印單鏈表
system("pause");
return 0;
}

運行界面

 

      分享如上,望共同進步!如有錯誤,望斧正!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章