インタビューの質問: 長さが不明な単一リンクリストの中間ノードを素早く見つけるにはどうすればよいですか?

インタビューの質問: 長さが不明な単一リンクリストの中間ノードを素早く見つけるにはどうすればよいですか?

バックグラウンド

私は偶然、インタビューの質問に遭遇しました。「長さが不明な単一リンクリストの中間ノードを素早く見つけるにはどうすればよいですか?」

方法

最初に思いついたのは非常に単純なトラバース方法で、その後、高速ポインタと低速ポインタの方法を学びました。

一般的な方法

原理

一般的な方法は非常に簡単で、まず単一リンク リストを走査して、単一リンク リストの長さを決定します。次に、ヘッド ノードから開始して再度 N/2 回ループし、単一リンク リストの中間ノードを見つけます。

アルゴリズムの複雑さは O(N+N/2)=O(3N/2) です。

コード
void common_found_List(Linklist *L,int len)
{
    
    
	Linklist *mid;
	int i = 0;
	Elemtype e;
	mid = L;
	len = len/2;
	while(i<=len)
	{
    
    
		mid = mid->next;
		i++;
	}
	e = mid->data;
	printf("The middle data of the list is :%d\n",e);
}

高度な方法

共通検索方法の最適化→★★★ポインタの速度と速度の遅さ★★★

原理

2 つのポインターp とMid を、単一リンク リストのヘッド ノードを指すように設定します。このうちpの移動速度はmidの2倍です。*p が終了ノードを指す場合、*mid も中間ノードを指します。

アルゴリズムの複雑さは O(N/2) です。

コード
void fast_slow_List(Linklist *L)
{
    
    
	Linklist *f,*mid;
	Elemtype e;

	f = L;
	mid = L;

	while(f->next)
	{
    
    
		if(f->next->next)
		{
    
    
			f = f->next->next;
			mid = mid->next;
		}
		else
		{
    
    
			f = f->next;
		}
	}
	e = mid->next->data;
	printf("The middle data of the list is :%d\n",e);
}

実験の過程と結果

合計コード
//<库函数>
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<math.h>

//<相关参数的宏定义>
#define Len sizeof(Node)
#define N 20                              
typedef int Elemtype;

typedef struct Node
{
    
    
	Elemtype data;
	struct Node* next;
}Node;

typedef struct Node Linklist;

//功能函数
Linklist* Creat_L();
void Out_Linklist(Linklist *h);
void fast_slow_List(Linklist *L);
void common_found_List(Linklist *L,int len);
int Length_list(Linklist *L);

void main()
{
    
    
	Linklist *L;
	int k ;
	int i ;
	int len;
	Elemtype x;

	printf("		《 Welcome to use the founction 》\n");
	printf("	    The founction can offer following service\n");
	printf("		*******Please first Initlist*******\n\n");
	printf("		1、Initlist          ->创建单链表\n");
	printf("		2、Insertlist        ->输出链表长度操作\n");
	printf("		3、common_Foundlist  ->普通方法查找中间元素操作\n");
	printf("		4、fast_Foundlist    ->高级方法查找中间元素操作\n");
	printf("		0、Exitlist          ->退出操作\n\n\n");
	printf("        Please choose following digital:1、2、3、0\n");
	printf("               Finish your idea!!!!!!\n");
	do
	{
    
    
		printf("\n\nPlease Input your choice:");
		scanf("%d",&k);
		switch(k)
		{
    
    
		case 1:
			{
    
    
				L = Creat_L(); 
				Out_Linklist(L);
			}break;
		case 2:
			{
    
    
				len = Length_list(L);
				printf("The length of the list is:%d\n",len);
			}break;
		case 3:
			{
    
    
				len = Length_list(L);
				common_found_List(L,len);
			}break;
		case 4:
			{
    
    
				fast_slow_List(L);
				Out_Linklist(L);
			}break;
		}
	}while(k!=0);
}

// <随机创建单链表>
Linklist* Creat_L()
{
    
    
	int count = 0;
	Linklist *h,*p,*s;
	Elemtype x;
	h = (Node*)malloc(Len);
	h->next = NULL;	
	p = h;
	//printf("Please Enter the FIRST Node data: ");
	//scanf("%d",&x);
	while(count < N)                          //假设终止条件
	{
    
    
		x = rand() % 50;                      //随机生成各节点,创建单链表
		s = (Node*)malloc(Len);	
		s->data = x;                          //赋值		
		s->next = NULL;
		p->next = s;
		p = s;	
		//printf("Please Enter the NEXT  Node data: ");
		//scanf("%d",&x);
		count++;
	}
	return h;
}

//<输出函数>
void Out_Linklist(Linklist *h)
{
    
    
	Linklist *p;
	p  = h->next;
	printf("Output Linklist:\n");
	while(p)
	{
    
    
		if(p->next!=NULL)
		{
    
    
			printf("%d -> ",p->data);
			p = p->next;
		}
		else
		{
    
    
			printf("%d",p->data);
			p = p->next;
		}
	}
}

// <快慢指针查找函数:使用快慢指针查找中间值的操作,时间复杂度为O(N/2)>
void fast_slow_List(Linklist *L)
{
    
    
	Linklist *f,*mid;
	Elemtype e;

	f = L;
	mid = L;

	while(f->next)
	{
    
    
		if(f->next->next)
		{
    
    
			f = f->next->next;
			mid = mid->next;
		}
		else
		{
    
    
			f = f->next;
		}
	}
	e = mid->next->data;
	printf("The middle data of the list is :%d\n",e);
}

//<长度函数>
int Length_list(Linklist *L)
{
    
    
	int count = 0;
	Linklist *p;

	p = L;
	while(p->next)
	{
    
    
		p = p->next;
		count++;
	}
	//printf("The length of the list is:%d\n",count);
	return count;
}

// <普通方法函数>
void common_found_List(Linklist *L,int len)
{
    
    
	Linklist *mid;
	int i = 0;
	Elemtype e;
	mid = L;
	len = len/2;
	while(i<=len)
	{
    
    
		mid = mid->next;
		i++;
	}
	e = mid->data;
	printf("The middle data of the list is :%d\n",e);
}
演算結果

ここに画像の説明を挿入

要約する

高速ポインタ アルゴリズムと低速ポインタ アルゴリズムを使用して単一リンク リストの中間ノードを見つけると、一般的なアルゴリズムよりも約 3 倍高速になります。もちろん、この例では速度差はありませんが、要素が多い場合には、より顕著に差が生じます。

さらに高度な方法で面接時に加点!

おすすめ

転載: blog.csdn.net/MZYYZT/article/details/113437641