Single Chain List Integration in C Language Learning


Organize the learning process of the list.

1. Implementation of Single Chain List

1.1 Chain List Nodes

There are two areas in the node, one data field and one pointer field.

struct node
{
	int data;				//Data field, you can add data and data type.
	struct node *Next;		//Pointer to Next Node
};

A struct node is just a structure, does not consume memory, and does not generate variables. It is just a template for a node, which is called directly in future practical needs.

1.2 heap memory usage

Why use heap memory? As mentioned earlier about memory, heap memory requires programmer's own release, which is more flexible. But if you use a stack, the program's own release is not flexible enough to match our list of chains.

Heap memory creation chain table steps:

  1. Request heap memory, size as a node size.
  2. Clean up heap memory because it is dirty. Otherwise there may be some messy data.
  3. Treat the requested heap memory as a new node.
  4. Populate new nodes into data and pointer fields.

Initial creation of 1.3 chained lists

#include <stdio.h>
#include <stdlib.h>
struct node
{
	int data;				//Data field, you can add data and data type.
	struct node *Next;		//Pointer to Next Node
};
int main()
{
	/*Requesting space for nodes now does not precede malloc because it seems that in recent C standards, malloc converts itself to type 1, which may have an impact if you add it. Of course, there is nothing wrong with it.*/
	struct node *p = malloc(sizeof(struct node));	
	if(NULL == p)
	{
		prrintf("malloc error!!\n");
		return -1;
	}
	//Clean up memory for applications (typically useless, I rarely use it myself)
	bzero(p,sizeof(struct node ));
	//Put data in memory
	p->data = 1;		//Put the value in the data field.
	p->Next = NULL;  //Points to the first address of the next node.
}

1.4 Perfect the list of chains and assign values

#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
struct node
{
	int data;				//Data field, you can add data and data type.
	struct node *Next;		//Pointer to Next Node
};
int main()
{
	struct node *Head = NULL;		 //Head Pointer
	/*Request space for nodes, malloc is no longer preceded by type, because it seems that in the recent C standard, malloc converts itself to type, and if you add it, it may have an impact. Of course, there is nothing wrong with it, just see your personal preferences*/
	struct node *p =malloc(sizeof(struct node));	
	Head = p;						 //Assign the value of the first node to the head node
	if(NULL == p)
	{
		prrintf("malloc error!!\n");
		return -1;
	}
	//Clean up memory for applications
	bzero(p,sizeof(struct node ));
	//Put data in memory
	p->data = 1;		//Put the value in the data field.
	p->Next = NULL;  //Points to the first address of the next node.
/**************************************/
	
	struct node *p1 = malloc(struct node);	
	if(NULL == p1)
	{
		prrintf("malloc error!!\n");
		return -1;
	}
	//Clean up memory for applications
	bzero(p1,sizeof(struct node ));
	//Put data in memory
	p1->data = 2;		//Put the value in the data field.
	p->Next = p1;  //Points to the first address of the next node.
	/***********************************************/
	struct node *p2 = malloc(struct node);	
	if(NULL == p2)
	{
		prrintf("malloc error!!\n");
		return -1;
	}
	//Clean up memory for applications
	bzero(p1,sizeof(struct node ));
	//Put data in memory
	p2->data = 3;		//Put the value in the data field.
	P1->Next = p2;  //Points to the first address of the next node.
}

So we've created a chain table with three nodes.
So let's have a quick look at this list

#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
struct node
{
	int data;				//Data field, you can add data and data type.
	struct node *Next;		//Pointer to Next Node
};
int main()
{
	struct node *Head = NULL;		 //Head Pointer
	/*Request space for nodes, malloc is no longer preceded by type, because it seems that in the recent C standard, malloc converts itself to type, and if you add it, it may have an impact. Of course, there is nothing wrong with it, just see your personal preferences*/
	struct node *p = malloc(sizeof(struct node));
	Head = p;						 //Assign the value of the first node to the head node
	if(NULL == p)
	{
		printf("malloc error!!\n");
		return -1;
	}
	//Clean up memory for applications
	bzero(p,sizeof(struct node ));
	//Put data in memory
	p->data = 1;		//Put the value in the data field.
	p->Next = NULL;  //Points to the first address of the next node.
/**************************************/
	
	struct node *p1 = malloc(sizeof(struct node));
	if(NULL == p1)
	{
		printf("malloc error!!\n");
		return -1;
	}
	//Clean up memory for applications
	bzero(p1,sizeof(struct node ));
	//Put data in memory
	p1->data = 2;		//Put the value in the data field.
	p->Next = p1;  //Points to the first address of the next node.
	/***********************************************/
	struct node *p2 = malloc(sizeof(struct node));
	if(NULL == p2)
	{
		printf("malloc error!!\n");
		return -1;
	}
	//Clean up memory for applications
	bzero(p2,sizeof(struct node ));
	//Put data in memory
	p2->data = 3;		//Put the value in the data field.
	p1->Next = p2;  //Points to the first address of the next node.
	/*****************************************************/
	/****Visit ****/
	printf("node p data = %d\n",p->data);
	printf("node p1 data = %d\n",p->Next->data);
	printf("node p2 data = %d\n",p->Next->Next->data);
}

1.5 Chain List Optimization

The code just now looks cumbersome, because we've just reused the Open Space function, so we can wrap it up and call it. Later we all need to improve the code, so we need to improve it here first

#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
struct node
{
	int data;				//Data field, you can add data and data type.
	struct node* Next;		//Pointer to Next Node
};
struct node *create(int data)
{
	struct node* p = malloc(sizeof(struct node));		
	if (NULL == p)
	{
		printf("malloc error!!\n");
		return NULL;
	}
	bzero(p, sizeof(struct node));
	p->data = data;		
	p->Next = NULL;  
	return  p;
}	
int main()
{
	struct node* Head = NULL;
	Head = create(1);
	Head->Next = create(2);
	Head->Next->Next = create(3);
	/****Visit ****/
	printf("node p data = %d\n", Head->data);
	printf("node p1 data = %d\n", Head->Next->data);
	printf("node p2 data = %d\n", Head->Next->Next->data);
}

Here we first use the head node to access one by one. If we do not use the head node to access, then our chain list is meaningless, because the function of the chain list is to access the next node through the previous node.

2. Basic Operation of Chain List

Insertion of 2.1 Chain List

2.1.1 Tail Interpolation

Tail insertion is easier because there is no need to change the previous data.
Let's first look at a diagram to make it easier for us to understand the insertion of a chain table:

Although the picture is ugly, it is clear that we need a header node to make it easy for us to find the first node of the chain table, which does not count in the length of the chain table.
The first step in tail interpolation is to find the tail, then change the pointing null of the tail node to the data field pointing to the new node, and point the pointing field of the new node to the null.

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

struct node
{
	int data;
	struct node* Next;
};
 /*Build nodes to open up space*/
struct node *create_node(int data)
{
	struct node* p = malloc(sizeof(struct node));
	if (NULL == p)
	{
		printf("malloc error!\n");
		return - 1;
	}
	p->data = data;
	p->Next = NULL;
}
 /*Tail interpolation function*/
void insert_tail(struct node *Head,struct node *New)
{
	
	struct node *p = Head;	//Avoid misunderstandings
    /*Traverse the list to find the tail node*/
    while(NULL != p->Next)
    {
		p = p->Next;
    }
    /*After finding the tail node, change the direction of its pointer field*/
    p->Next = New;
    New->Next = NULL;
}
int main()
{
	struct node* Head = create_node(0); 		//Head node, so that we can find the first node of the list
     /*End insertion through the head node*/
	insert_tail(Head,create_node(1));
	insert_tail(Head,create_node(2));
   insert_tail(Head,create_node(3));
    /*Print Head Node Value*/
	printf("P1 = %d\n",Head->data);
    /*Print the value of the first point*/
	printf("P2 = %d\n", Head->Next->data);
    /*Print the value of the second point*/
	printf("p3 = %d\n", Head->Next->Next->data);
    /*Print the value of the third point*/
   printf("p4 = %d\n", Head->Next->Next->Next->data);
	system("pause");
	return 0;
}

2.1.2 head interpolation

Head insertion is the continuous insertion of new nodes into the head.
Same picture first:

This order is very important, first point the pointer field of the new node to the original first node, then point the original header node to the new data field.

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


struct node
{
	int data;
	struct node* Next;
};
 /*Build nodes to open up space*/
struct node *create_node(int data)
{
	struct node* p = malloc(sizeof(struct node));
	if (NULL == p)
	{
		printf("malloc error!\n");
		return - 1;
	}

	p->data = data;
	p->Next = NULL;
}
 /*Head Interpolation Function*/
void insert_hand(struct node *Head,struct node *New)
{
	 /*Head Interpolation finishes without traversing directly to the first node
     First point the pointer of the new node to the original first node*/
     New->Next = Head->Next;
     /*The original header node points to the new node now*/
     Head->Next = New;
}
int main()
{
	struct node* Head = create_node(0); 		//Head node, so that we can find the first node of the list
     /*End insertion through the head node*/
	insert_hand(Head,create_node(1));
	insert_hand(Head,create_node(2));
    insert_hand(Head,create_node(3));
    /*Print Head Node Value*/
	printf("P1 = %d\n",Head->data);
    /*Print the value of the first point*/
	printf("P2 = %d\n", Head->Next->data);
    /*Print the value of the second point*/
	printf("p3 = %d\n", Head->Next->Next->data);
    /*Print the value of the third point*/
    printf("p4 = %d\n", Head->Next->Next->Next->data);
	system("pause");
	return 0;
}

The value of the head node is printed here, so you don't need to worry about this if you print the chain list.

3. Traversal of Chain Lists

What is traversal: it is equivalent to taking one egg from the basket, not two at a time, or the same egg twice, according to a certain rule, first and then the second.
For a chain table, the nodes are pulled out one by one.
For arrays, the first to last of the arrays are taken out one by one.
Key points to traverse:
1) Can not be omitted
2) Cannot repeat
3) Pursue efficiency (others only need 10 seconds to come one minute and finish)

How to traverse:
You want to traverse a list of chains, first you have to find the head and the end, you know the relationship, then from beginning to end, the trailing node of the list is characterized by its pointer field pointing to empty.
That's what chain lists mean. We write code directly.

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

struct node
{
	int data;
	struct node* Next;
};
 /*Build nodes to open up space*/
struct node *create_node(int data)
{
	struct node* p = malloc(sizeof(struct node));
	if (NULL == p)
	{
		printf("malloc error!\n");
		return - 1;
	}
	p->data = data;
	p->Next = NULL;
}
 /*Tail interpolation function*/
void insert_tail(struct node *Head,struct node *New)
{
	
	struct node *p = Head;	//Avoid misunderstandings
    /*Traverse the list to find the tail node*/
    while(NULL != p->Next)
    {
		p = p->Next;
    }
    /*After finding the tail node, change the direction of its pointer field*/
    p->Next = New;
    New->Next = NULL;
}
 /*Head Interpolation Function*/
void insert_hand(struct node *Head,struct node *New)
{
	 /*Head Interpolation finishes without traversing directly to the first node
     First point the pointer of the new node to the original first node*/
     New->Next = Head->Next;
     /*The original header node points to the new node now*/
     Head->Next = New;
}
/*Traversing a list of chains*/
void bianli(struct Node *Head)
{
	struct node* p = Head;
	while (NULL != p->Next)
	{
		p = p->Next; //One node moves backwards and backwards;
		printf("node data = %d \n",p->data);//Print each node
	}
}
int main()
{
	struct node* Head = create_node(0); 		//Head node, so that we can find the first node of the list
     /*End insertion through the head node*/
	insert_tail(Head,create_node(1));
	insert_tail(Head,create_node(2));
  insert_tail(Head,create_node(3));
	bianli(Head);
	system("pause");
	return 0;
}

There's actually a key point here:

Think about why P = p->Next;Write before printing. What happens if you write after.


This is not to print out our header node. But our last node did not print out. In fact, this is the point that the chain table has a header node pointing to the first pointer.

4. Chain List Node Deletion

Steps to delete the list:
1) Traverse the list, otherwise how can you find the corresponding list?
2) Make a judgment with the list node, if the same, then find it and delete it
3) Determine whether it is a tail node.
4) Use a node that points to the previous node where we traverse the node so that we can operate easily
5) Release the space of deleted nodes, otherwise memory leaks will occur
Direct Up Code

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

struct node
{
	int data;
	struct node* Next;
};
 /*Build nodes to open up space*/
struct node *create_node(int data)
{
	struct node* p = malloc(sizeof(struct node));
	if (NULL == p)
	{
		printf("malloc error!\n");
		return NULL;
	}
	p->data = data;
	p->Next = NULL;
	return p;
}

/*Delete Node*/
void deletNode(struct Node* Head, int nData)
{
	//Traversing a list of chains
	struct node* p = Head;
	//Define a node
	struct node* pPrev = NULL;
	while (NULL != p->Next)
	{
		pPrev = p;//Node points to the previous traversing node
		p = p->Next;

		//Find Node, Find
		if (p->data == nData)
		{
			//Determine whether it is a tail node
			if (NULL != p->Next)
			{
				pPrev->Next = NULL;
				free(p);
			}
			else
			{
				pPrev->Next = p->Next;
				free(p);
			}
            printf("Delete complete\n");
			return 0;
		}
	}
    printf("Node not found\n");
	return -1;
}


5. Inverse Output of Single-Chain List

Joined table reverse output step
1) Determine if the join table is empty or has only one node
2) Traversing through previous chains
3) Insert the previous list of chains into a new list continuously with header insertion
4) Traverse through a new list of chains

Let's look at the code

void reverseLink(struct node* Head)
{
	struct node* p = Head->Next; //First Node
	struct node* pBack;
	//If there is only one node or no node
	if ((NULL == p) || (NULL == p->Next))
		return;
	while (NULL != p->Next)
	{
		pBack = p->Next; //Change the original tail node to the first node now
		if (p == Head->Next) 
		{
			p->Next = NULL;
		}
		else
		{
			p->Next = Head->Next;
		}
		Head->Next = p;
		p = pBack;
	}
	insert_hand(Head,p);
}

6. Complete Code

Because this article has been written for a long time, there may be some inconsistencies in the code because of the busy time in the middle, the interview and the lack of time to write it. Also, the compilers used are different, causing some problems. Attach the complete code here

#include <stdio.h>
#include <stdlib.h>
/*Define Structures*/
struct node
{
	int data;
	struct node* Next;
};
 /*Build nodes to open up space*/
struct node *create_node(int data)
{
	struct node* p = malloc(sizeof(struct node));
	if (NULL == p)
	{
		printf("malloc error!\n");
		return NULL;
	}
	p->data = data;
	p->Next = NULL;
	return p;
}
 /*Tail interpolation function*/
void insert_tail(struct node *Head,struct node *New)
{
	
	struct node *p = Head;	
    /*Traverse the list to find the tail node*/
    while(NULL != p->Next)
    {
		p = p->Next;
    }
    /*After finding the tail node, change the direction of its pointer field*/
    p->Next = New;
    New->Next = NULL;
}
 /*Head Interpolation Function*/
void insert_hand(struct node *Head,struct node *New)
{
	 /*Head Interpolation finishes without traversing directly to the first node
     First point the pointer of the new node to the original first node*/
     New->Next = Head->Next;
     /*The original header node points to the new node now*/
     Head->Next = New;
}
/*Traversing a list of chains*/
void traverseLink(struct node *Head)
{
	struct node* p = Head;
	printf("Start traversal\n");
	while (NULL != p->Next)
	{
		p = p->Next;
		printf("node data = %d\n",p->data);
	}
	printf("Traverse complete\n");
}
/*Delete Node*/
int deletNode(struct node *Head, int nData)
{
	//Traversing a list of chains
	struct node* p = Head;
	//Define a node
	struct node* pPrev = NULL;
	while (NULL != p->Next)
	{
		pPrev = p;//Node points to the previous traversing node
		p = p->Next;

		//Find Node, Find
		if (p->data == nData)
		{
			//Determine whether it is a tail node
			if (NULL == p->Next)
			{
				pPrev->Next = NULL;
				free(p);
			}
			else
			{
				pPrev->Next = p->Next;
				free(p);
			}
            printf("**********Delete complete**********\n");
			return 0;
		}
	}
    printf("Node not found\n");
	return -1;
}

int  reverseLink(struct node* Head)
{
	struct node* p = Head->Next;
	struct node* pBack;
	//If there is only one node or no node
	if ((NULL == p) || (NULL == p->Next))
	{
		printf("Chain list cannot be reversed\n");
		return -1;
	}
	while (NULL != p->Next)
	{
		pBack = p->Next; //Change the original tail node to the first node now
		if (p == Head->Next)
		{
			p->Next = NULL;
		}
		else
		{
			p->Next = Head->Next;
		}
		Head->Next = p;
		p = pBack;
	}
	insert_hand(Head,p);
	printf("*********After reverse order*********\n");
}
int main()
{
	struct node* Head = create_node(0); 		//Head node, so that we can find the first node of the list
     /*End insertion through the head node*/
	insert_hand(Head,create_node(1));
	insert_hand(Head,create_node(2));
	insert_hand(Head,create_node(3));
	insert_hand(Head,create_node(4));
	/*
	* traverseLink(Head);
	* reverseLink(Head);
	* traverseLink(Head);
	*/

	/*
	* traverseLink(Head);
	* deletNode(Head,?);
	* traverseLink(Head);
	*/
	return 0;
}

Tags: C data structure linked list

Posted on Thu, 16 Sep 2021 13:08:54 -0400 by Daveyz1983