Pregunta de la entrevista: ¿Cómo encontrar rápidamente el nodo medio de una lista enlazada individualmente de longitud desconocida?

Pregunta de la entrevista: ¿Cómo encontrar rápidamente el nodo medio de una lista enlazada individualmente de longitud desconocida?

fondo

Me encontré con una pregunta de la entrevista por casualidad: ¿Cómo encontrar rápidamente el nodo medio de una lista enlazada individualmente de longitud desconocida?

método

Lo primero que pensé fue un método transversal muy simple, y luego aprendí un método de punteros rápidos y lentos.

método común

principio

El método común es muy simple, primero recorra la lista de enlaces simples para determinar la longitud de la lista de enlaces simples. Luego comience desde el nodo principal y realice un bucle N/2 veces nuevamente para encontrar el nodo medio de la lista enlazada individualmente.

La complejidad del algoritmo es O(N+N/2)=O(3N/2).

el código
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);
}

método avanzado

Optimizar el método de búsqueda común→★★★Velocidad y puntero lento★★★

principio

Establezca los dos punteros p y mid para que apunten al nodo principal de la lista enlazada individualmente. Entre ellos, la velocidad de movimiento de p es el doble de la de mid. Cuando *p apunta al nodo final, *mid también apuntará al nodo medio.

La complejidad del algoritmo es O(N/2).

el código
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);
}

Proceso experimental y resultados.

codigo total
//<库函数>
#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);
}
resultado de la operación

inserte la descripción de la imagen aquí

Resumir

Usar el algoritmo de puntero rápido y lento para encontrar los nodos intermedios de la lista enlazada individualmente es aproximadamente 3 veces más rápido que el algoritmo común. Por supuesto, no hay diferencia de velocidad en este ejemplo, cuando hay muchos elementos, habrá una brecha más obvia.

¡Además, los métodos avanzados sumarán puntos durante su entrevista! ! ! ! ! !

Supongo que te gusta

Origin blog.csdn.net/MZYYZT/article/details/113437641
Recomendado
Clasificación