Personal notes on data structure Lesson 8 circular linked list & linked list

Keywords: data structure linked list

Circular linked list

As long as the two ends of the linked list are connected, it becomes a circular linked list, which is usually called circular linked list

It should be noted that although the circular linked list is a ring, it is still a linked list in essence. Therefore, in the circular linked list, you can still find the head pointer and the first element node. The only difference between a circular linked list and an ordinary linked list is that the circular linked list is connected end to end, and everything else is exactly the same

Establishment and display of circular linked list

When establishing a circular linked list, there is one more tail pointer pointing to the first node than an ordinary linked list.

person * initPerson(int num){
	person * head = (person *)malloc(sizeof(person));
	head -> data = 1;
	head -> next = NULL;
	person * temp = head;
	for(int i = 2;i<=num;i++){
		person * body = (person *)malloc(sizeof(person));
		body -> next =NULL;
		body -> data = i;
		temp -> next = body;
		temp = temp -> next;
	}
	temp -> next = head;
	return head;
}

When display ing a circular linked list, you cannot use the previous tail pointer pointing to NULL to determine that the linked list is over. You need to determine that the tail pointer points to the head node before it is over

void display(person * head){
	person * temp = head;
	while(temp){
		printf("%d ",temp -> data);
		temp = temp -> next;
		if(temp== head){
			printf("\n");
			break;
		}
	}
}

Joseph Ring

That is, it is known that n individuals (numbered 1, 2, 3,..., n respectively) sit around a round table and count clockwise from number k to M; His next person starts from 1 or starts counting clockwise. The person who counts to m goes out of the line and repeats it in turn until there is one person left in the round table.

Full code:

#include <stdio.h>
#include <stdlib.h>

typedef struct node{
	struct node * next;
	int data ;
}person;

person * initPerson(int num){
	person * head = (person *)malloc(sizeof(person));
	head -> data = 1;
	head -> next = NULL;
	person * temp = head;
	for(int i = 2;i<=num;i++){
		person * body = (person *)malloc(sizeof(person));
		body -> next =NULL;
		body -> data = i;
		temp -> next = body;
		temp = temp -> next;
	}
	temp -> next = head;
	return head;
}

void display(person * head){
	person * temp = head;
	while(temp){
		printf("%d ",temp -> data);
		temp = temp -> next;
		if(temp== head){
			printf("\n");
			break;
		}
	}
}

void findKiller(person * head,int k, int m){
	person * temp = head;
	person * findK = head;
	while (findK -> data != k){
		findK = findK -> next;
	}
	temp = findK;
	while(findK -> next != findK){
		for(int i = 1;i<m;i++){
			temp = findK;
			findK = findK -> next;
		}
		temp -> next = findK -> next;
		printf("The number of the listed person is%d\n",findK -> data);
		free(findK);
		findK = temp -> next;
	}
	printf("The number of the last person listed is%d\n",findK -> data);
	free(findK);
}

int main(){
	printf("Please enter the total number of people\n");
	int num;
	scanf("%d",&num);
	person * head = initPerson(num);
	display(head);
	
	int k;
	scanf("%d",&k);
	printf("From the first%d Individual start counting:\n",k);

	
	int m;
	scanf("%d",&m);
	printf("Count to%d The following people are listed:\n",m);

	
	findKiller(head,k,m);
	
	return 0;
}

Judge linked list

That is to judge whether there are links in a linked list

  1. This problem is often solved by the fast and slow pointer, that is, each step of the slow pointer, the fast pointer takes two steps and keeps going. If there is a ring in the linked list, the speed pointer must be encountered in the ring. If it is encountered, it will output true, and if not, it will output false
  2. From this problem, where is the entrance of the ring, how many nodes are there in the ring, and how many nodes are there in the linked list

In the output of the linked list, because we want to traverse the whole linked list, we can use the traversal method to detect whether the addresses of all points are the same to judge whether there is a ring, or the hash table method to judge.
If the fast and slow pointers are used to solve the problem, the fast pointer will take two steps every time the slow pointer takes one step forward. Therefore, after the slow pointer enters the ring, each operation will shorten the distance from the fast pointer to the slow pointer by one step. If this continues, the distance between the two will be gradually reduced until they meet. Because they are in the same ring, Therefore, the distance between the two will not be greater than the length of the ring, so the slow pointer must not have completed a circle until the two meet

It can be seen from the above that when the fast and slow pointers meet, the slow pointer must not have finished the linked list. It is assumed that the fast pointer has cycled n times in the ring (1 < = n). Assuming that the slow pointer takes s steps, the fast pointer takes 2s steps. Since the number of steps taken by the fast pointer is s+nr, the following equation can be obtained:
2s = s+n*r —> s = n * r

If the length of the entire linked list is assumed to be L, the distance between the entrance and the meeting point is x, and the distance from the starting point to the point at the entrance is a, then:
a + x = s= n* r;
a + x = (n-1) * r + r = (n - 1) * r + (L - a)
Calculate from the length of the ring = total length of the linked list - the distance from the starting point to the entry point:
a = (n - 1) * + (L - a - x)

All the above questions can nest these formulas, so the summary code is:

#include <stdio.h>
#include <stdlib.h>

typedef struct line{
	struct line * next;
	int data;
};

line * initLine(int num ,int data){
	line * head = (line *)malloc(sizeof(line));
	head -> data = 1;
	head -> next = NULL;
	line * temp = head;
	for(int i = 2 ; i <= data ;i++){
		line * body = (line *)malloc(sizeof(line));
		body -> data = i;
		body -> next =NULL;
		temp -> next = body;
		temp = temp -> next;
	}
	line * round = head;
	for(int i = 1;i < num;i++){
		round = round -> next;
	}
	temp -> next = round;
	return head;
}

void display(line * head){
	line * temp = head;
	int i = 0;
	while(temp){
		printf("%d ",temp -> data);
		temp = temp -> next;
		i++;
		line * round = head;
		for(int j = 1;j< i ;j++){
			if(temp == round){
				printf("\n");
				return;
			} 
			round = round -> next; 
		}
	}
}

int checkRound(line * head){
	line * quick = head;
	line * slow = head;
	int i = 0;
	while(slow != NULL && quick -> next != NULL){
		i++;
		slow = slow -> next;
		quick = quick -> next -> next;
		if (slow == quick){
			printf("%d\n",i);
			break;
		}
	}
	line * ptr = head;
	while(slow != NULL && ptr != NULL){
		slow = slow -> next;
		ptr = ptr -> next;
		if(slow == ptr){
			return ptr -> data; 
		}
	}
	
}

int main(){
	line * head = initLine(28,30);
	display(head);
	
	printf("There are links in the linked list,The inlet of the ring is:%d\n",checkRound(head));

	
	return 0;
}

This only solves the problem of judging the entrance, and others can be analogized
reference material: Judge whether the linked list has links

Posted by Merve on Wed, 06 Oct 2021 21:17:00 -0700