單鏈表--操作總結

花了一個小時的時間做了一個小小的總結,希望對各位親,有幫助。廢話不多說。開始吧!

本文主要針對,單鏈表的創建。

對無環鏈表的反轉,打印。

有環鏈表的判別,入環點的尋找,打印。

// 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
證明完畢。



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