花了一個小時的時間做了一個小小的總結,希望對各位親,有幫助。廢話不多說。開始吧!
本文主要針對,單鏈表的創建。
對無環鏈表的反轉,打印。
有環鏈表的判別,入環點的尋找,打印。
// TestListHuan.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#define N 20 //鏈表的長度
using namespace std;
struct ListNode
{
int data;
ListNode *next;
};
//打印鏈表
void print(ListNode *p,ListNode *flagH)
{
ListNode *q=p;
int count=0;
while(q)
{
cout<<" "<<q->data;
q=q->next;
if(q==flagH)
{
count++;
if(count>1)
{
cout<<" "<<flagH->data<<endl;
break;
}
}
}
cout<<endl;
}
//創建無環鏈表
ListNode *creatList()
{
ListNode *pHead,*pRear,*p;
int x;
string listName;
pHead=(ListNode *)malloc(sizeof(ListNode));
pRear=pHead;
p=pHead;
cout<<"Please input the listName:"<<endl;
cin>>listName;
for(int i=0;i<N;i++)
{
x=rand()%100;
pHead=(ListNode*)malloc(sizeof(ListNode));
pHead->data=x;
pRear->next=pHead;
pRear=pHead;
}
pRear->next=NULL;
print(p->next,NULL);
return p->next;
}
ListNode *creatListHuan()//創建有環鏈表
{
ListNode *pHead,*pRear,*p,*t;
int x;
string listName;
pHead=(ListNode *)malloc(sizeof(ListNode));
pRear=pHead;
p=pHead;
cout<<"Please input the listName:"<<endl;
cin>>listName;
for(int i=0;i<N;i++)
{
x=rand()%100;
pHead=(ListNode*)malloc(sizeof(ListNode));
pHead->data=x;
pRear->next=pHead;
pRear=pHead;
if(i==4)
{
t=pRear;
}
}
pRear->next=t;
return p->next;
}
//反轉無環鏈表
ListNode *revrseList(ListNode *p)
{
if(p==NULL||p->next==NULL)
return p;
ListNode *pHead=NULL;
ListNode *q=p;
ListNode *t=NULL;
t=NULL;
while(q)
{
pHead=q->next;
q->next=t;
t=q;
q=pHead;
}
return t;
}
///下面談下有環的情況
//驗證該鏈表是否有環
ListNode *getHuan(ListNode *p)
{
if(p==NULL||p->next==NULL)
return NULL;
ListNode *q=p;
ListNode *t=p;
while(q!=NULL)
{
t=t->next->next;
if(t==NULL)
break;
q=q->next;
if(q==t)
break;
}
if(t)
return t;
return NULL;
}
//*p 鏈表頭結點,*q是相遇結點 這個是重點哦!有不懂的留言哦!
ListNode *getDot(ListNode *p,ListNode *q)
{
if(p==NULL||p->next==NULL)
return NULL;
while(p!=NULL)
{
p=p->next;
q=q->next;
if(p==q)
break;
}
if(p)
return p;
return NULL;
}
int main()
{
printf("Hello World!\n");
ListNode *p,*q,*pH,*qH;
p=creatList();
q=revrseList(p);
print(q,NULL);
//*****下面談下有環的事情
pH=creatListHuan();
qH=pH;
ListNode *flag=getHuan(pH);
if(flag)
{
cout<<"有環"<<endl;
ListNode *hP=getDot(pH,flag);
print(qH,hP);
cout<<"入環點的值:"<<hP->data<<endl;
}
else
cout<<"無環"<<endl;
return 0;
}
兩個小問題:
1.在有環的情況下,爲什麼慢指針在沒有走完一整圈,就會和快指針相遇?
2.從相遇結點,和頭結點同時一步一步走,相遇點爲什麼就是入環點?
現在時間:2012年8月2日10:12:03
真的對不起大家,這麼久纔來回答這兩個小問題。
首先我們來看第一個問題:
爲什麼慢指針沒有走完一圈就會相遇。
我們可也是用反證法。
假設慢指針走完了一圈,他們才相遇的話,你可以再往前退,會發現,在此之前必會相遇。你可以做一個簡單的試驗,畫一個圈,圈上N個點,一開始兩個人,站在不同的點上,朝着同一方向,不同速度的移動。在那個慢的人沒有走完一圈的時候,他們就會相遇。
關於第二個問題:根據數學推理。得到
在兩個指針相遇的點,該點距離環入口點的距離,正好等於鏈表的頭節點到環入口點的距離!證明如下:
假設:頭結點到環入口點的距離爲x,整個鏈表長度爲L,相遇的時候距離環入口點的距離爲z,慢指針走的是快的一半。假設慢的走了s,r爲環的長度,則 s+nr=2s 即:s=nr
s=x+z;
x=s-z=nr-z=(n-1)r+r-z=(n-1)r+L-a-z
證明完畢。