Encontrar bucle
Información del tema
Para cualquier fracción verdadera N / M (0 <N <M), se puede encontrar el decimal correspondiente. Si almacena decimales cadena, para la sección de circulación mediante la representación de lista enlazada circular, todas las puntuaciones se pueden expresar como la siguiente forma de lista
de entrada: NM
salida: toda la sección ciclo
requisito: escribir una función para encontrar el punto de inicio de la sección de bucle tan eficientemente como sea posible: NODE * find( NODE * head, int * n )
. El valor de retorno de la función es el punto de inicio de la sección del bucle (el puntero p en la figura) y n es la longitud de la sección del bucle. Envíe también una función para convertir fracciones a decimales change( int n, int m, NODE * head )
.
Pre-código:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node * next;
} NODE;
NODE * find( NODE * , int * );
void outputring( NODE * );
void change( int , int , NODE * );
void outputring( NODE * pring )
{
NODE * p;
p = pring;
if ( p == NULL )
printf("NULL");
else
do {
printf("%d", p->data);
p = p->next;
} while ( p != pring );
printf("\n");
return;
}
int main()
{
int n, m;
NODE * head, * pring;
scanf("%d%d", &n, &m);
head = (NODE *)malloc( sizeof(NODE) );
head->next = NULL;
head->data = -1;
change( n, m, head );
pring = find( head, &n );
printf("ring=%d\n", n);
outputring( pring );
return 0;
}
/* Here is waiting for you.
void change( int n, int m, NODE * head )
{
}
NODE * find( NODE * head, int * n )
{
}
*/
Entrada de prueba | Espere salida | |
---|---|---|
Caso de prueba 1 | 1 3 |
ring=1 3 |
Caso de prueba 2 | 1 8 |
ring=1 NULL |
Caso de prueba 3 | 29 33 |
ring=1 87 |
Caso de prueba 4 | 2 7 |
ring=6 285714 |
responder
void change(int n, int m, NODE *head)
{
// 2/7 = 0.285714
NODE **array;//开辟一个数组,数组的内容是链表
NODE *p = head;//将head引向p
array = (NODE **) malloc(sizeof(NODE *) * m);//开辟的数组大小为链表头节点的大小*m,此处相当于开辟了7个
for (int k = 0; k < m; k++)
array[k] = NULL;
while (n != 0)
{
if (n * 10 % m == 0)
{
//恰好整除
p->next = (NODE *) malloc(sizeof(NODE));
p->next->data = n * 10 / m;
p->next->next = NULL;
n = 0;
}
else
{
//未整除情况
if (array[n] == NULL)
{
//该余数是第一次出现
array[n] = p->next = (NODE *) malloc(sizeof(NODE));//为后续下一个节点开辟空间,
// 同时也在array数组中记录下了是否出现过这个余数
p->next->data = n * 10 / m;//下一个节点的数据为第一次的除数2
n = n * 10 % m;//n此时被改变为余数
p = p->next;//p挪向下一个节点
}
else
{
//该余数不是第一次出现,则发现循环节
p->next = array[n];
n = 0;
}
}
}
}
NODE *find(NODE *head, int *n)
{
NODE *p, *q;
p = q = head->next;//p和q均指向head
while (p != NULL && q != NULL)
{
p = p->next;
q = q->next;
if (q != NULL)//q一次向后移动两个
q = q->next;
if (p == q)
break;//找到重合点则退出
}
if (q == NULL)
{
//如果q一直指向最后还没有找到重合的点那么就不循环了
*n = 0;
return NULL;
}
int ring = 1;
while (q->next != p)
{
//求环长
q = q->next;//q走的快,让q再走回来
ring++;
}
int count = 0;
q = p = head->next;//再一次从头开始
while (count < ring)
{
//p先向前走循环节步长的长度
count++;
p = p->next;
}
while (p != q)
{
//如果pq不相等说明未找到恰好一起的地方,还在前面非循环节的位置
p = p->next;
q = q->next;
}
*n = ring;
return p;
}