Implementation of single linked list

Posted by Third_Degree on Sat, 30 Oct 2021 14:49:33 +0200

        Headless one-way acyclic linked list: it has a simple structure and is generally not used to store data alone. In fact, it is more used as a substructure of other data structures, such as hash bucket, adjacency table of graph and so on. In addition, this structure appears a lot in the written interview.

        This linked list stores a data for each node and the address of the next node, which can string each node well.

Single linked list is created for the disadvantages of sequential list.

catalogue

  Structure creation

Implementation of function interface

void SLTNodeDestroy(SLTNode** pphead)

SLTNode* BuyListNode(SLTDataType x)

void SLTNodePushBack(SLTNode** pphead, SLTDataType x)

void SLTNodePopBack(SLTNode** pphead)

void SLTNodePushFront(SLTNode** pphead, SLTDataType x)

void SLTNodePopFront(SLTNode** pphead)

void SLTNodePrint(SLTNode* pphead)

SLTNode* SLTNodeFind(SLTNode* pphead, SLTDataType x)

void SLTNodeInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) 

void SLTNodeErase(SLTNode** pphead, SLTNode* pos)

Single linked list complete code

SList.h

SList.c

Code test.c

  Structure creation

typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

Implementation of function interface

//void SLTNodeInit(SLTNode** ps);  // The single linked list does not need to be initialized
//Destruction of single linked list
void SLTNodeDestroy(SLTNode** pphead);
//Tail insertion
void SLTNodePushBack(SLTNode** pphead, SLTDataType x);
//Tail deletion
void SLTNodePopBack(SLTNode** pphead);
//Head insert
void SLTNodePushFront(SLTNode** pphead, SLTDataType x);
//Header deletion
void SLTNodePopFront(SLTNode** pphead);
//Print single linked list
void SLTNodePrint(SLTNode* pphead);
//Find a data in the single linked list and return the address
SLTNode* SLTNodeFind(SLTNode* pphead, SLTDataType x);
//Insert a data before pos
void SLTNodeInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x); //It is not the data change of pos position, and there is no need to transfer the secondary pointer
//Delete pos location data
void SLTNodeErase(SLTNode** pphead, SLTNode* pos);

Is it found that many function interfaces are passed secondary pointers. Why?

     SLTNode* plist = NULL; // When testing the code, we initialize the first node and receive the pointer

     SLTNodePushBack(&plist, 1); // Suppose we insert the header here, which may change the header node, plist       It is a primary pointer. In order to change smoothly, we use a secondary pointer here (pointer variables are also variables).

    Otherwise, sltnodepushback (plist, 1); The plist is received by the formal parameter after it is passed. There is no way to find the plist point here         The address of that space. Although the space corresponding to the formal parameter is changed, the change of the formal parameter will not affect the argument. Plist actual       The space pointed to has not changed.

void SLTNodeDestroy(SLTNode** pphead)

void SLTNodeDestroy(SLTNode** pphead)
{
	SLTNode* cur = *pphead;
	while (cur != NULL)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = NULL;
		cur = next;
	}
}

//Destroy the linked list of dynamically opened space

void SLTNodeDestroy(SLTNode** pphead)   // The header pointer will be changed, so it is necessary to pass the secondary pointer
{
     SLTNode* cur = *pphead; // Assign the value of the first element to cur
     while (cur != NULL)   // When cur is empty, the node is deleted
    {
         SLTNode* next = cur->next; // Delete from scratch. When deleting a header node, record the of the next node in advance             Position to ensure that the following nodes can be found.
         free(cur); // Release node
        cur = NULL;
         cur = next; // The head node position becomes the position recorded in advance
    }
}

SLTNode* BuyListNode(SLTDataType x)

SLTNode* BuyListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	else
	{
		newnode->data = x;
		newnode->next = NULL;
	}
	return newnode;
}

Dynamically open up a node size space to store data and the address of the next node

SLTNode* BuyListNode(SLTDataType x)
{
     SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode)); // Dynamic development space
     if (newnode == NULL)   // If the development fails, end the process
    {
        printf("malloc fail\n");
        exit(-1);
    }
    else
    {
         newnode->data = x; // The location of a node stores a data
         newnode->next = NULL; // The next address pointed to by the node is empty
    }
     return newnode; // Return the address of the opened node
}

void SLTNodePushBack(SLTNode** pphead, SLTDataType x)

void SLTNodePushBack(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		//Find tail node
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

void SLTNodePushBack(SLTNode** pphead, SLTDataType x)
{
     SLTNode* newnode = BuyListNode(x); // When inserting data, open up a space and use newnode to receive the data                                                                       Open up a good space and an address
     if (*pphead==NULL)    //* pphead==NULL is empty, indicating that the first node has no data. When the linked list is empty
    {
        * pphead = newnode; // At this time, the newnode is assigned to the first empty node
    }
    else
    {
        // Find tail node
         SLTNode* tail = *pphead; // Use a pointer to record the tail node to avoid modifying the head node
         While (tail - > next! = null) / / if the next node is empty, the current node is not empty and is the last node
        {
             tail = tail->next; // The tail pointer constantly points to the address of the following node
        }
         tail->next = newnode; // The next node of the last node is assigned as the node to be inserted, which is equivalent to tail insertion
    }
}

void SLTNodePopBack(SLTNode** pphead)

void SLTNodePopBack(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	if ((*pphead)->next == NULL)
	{
		SLTNode* cur = *pphead;
		free(cur);
		cur = NULL;
	}
	else
	{
		SLTNode* prev = NULL;
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;
		prev->next = NULL;
	}
}

Delete the last node of the single linked list

void SLTNodePopBack(SLTNode** pphead)
{
     assert(pphead);// Judge whether the received node is a valid address
     assert(*pphead);// Judge whether the first node is empty. If it is empty, there is no node
     If (* pphead) - > next = = null) / / judge whether there is only one node in the linked list
    {
        SLTNode* cur = *pphead; 
         free(cur); // Release the first node
        cur = NULL;
    }
    else
    {
         SLTNode* prev = NULL; // Record the address of the previous node of the last node, and set it to null for the first time
         SLTNode* tail = *pphead;// Record the last node
         while (tail->next != NULL)   // The tail finally points to the last node
        {
             prev = tail; //perv is assigned the address of (original) tail
             tail = tail->next; // Tail points to the position of the next node
        }
        free(tail);
        tail = NULL;
         prev->next = NULL;// Prev stores the address of the penultimate node in the original linked list. At this time, it should be regarded as the tail node
    }
}

void SLTNodePushFront(SLTNode** pphead, SLTDataType x)

void SLTNodePushFront(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
}

Insert a data before the first position in the linked list

void SLTNodePushFront(SLTNode** pphead, SLTDataType x) / / pass the secondary pointer. The first pointer may be modified                                                                                                         Nodes
{
     SLTNode* newnode = BuyListNode(x); // Open up the nodes to join
     if (*pphead == NULL)   // Judge whether there are no nodes in the linked list
    {
        * pphead = newnode; // The first empty node is assigned newnode
    }
     else / / when there is at least one node in the linked list
    {
         newnode->next = *pphead;// The next node of the new node refers to the head node
        * pphead = newnode;// When the head node becomes a new node, it is equivalent to inserting the head
    }
}

void SLTNodePopFront(SLTNode** pphead)

void SLTNodePopFront(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* next = (*pphead)->next;
		free(*pphead);
		*pphead = next;
	}
}

Delete the first node in the linked list

void SLTNodePopFront(SLTNode** pphead)
{
     assert(pphead);// Judge whether the received node is a valid address
     assert(*pphead);// Judge whether the first node is empty. If it is empty, there is no node
     If (* pphead) - > next = = null) / / when the next node of the chain header node is empty, there is only one node in the single chain table
    {
         free(*pphead); // Release header node
        * pphead = NULL; // Head node null
    }
     else / / when the linked list has more than one node
    {
         SLTNode* next = (*pphead)->next;// Record the position of the next node of the header node in advance to prevent it from being found
         free(*pphead);// Release the header node. If there is the previous step, you are not afraid that the following node cannot be found
        * pphead = next; // At this time, the header node becomes the next node of the original node. At this time, the header is deleted
    }
}

void SLTNodePrint(SLTNode* pphead)

void SLTNodePrint(SLTNode* pphead)
{
	SLTNode* cur = pphead;
	while (cur!= NULL)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

Print data in single linked list

void SLTNodePrint(SLTNode* pphead)
{
     SLTNode* cur = pphead; // A pointer is used to represent the head node to avoid arbitrary change of the head node
     While (cur! = null) / / stop when cur is empty, indicating that the data of nodes that are not empty have been printed
    {
        printf("%d ", cur->data);
         cur = cur->next;// Cur keeps pointing to the next node
    }
    printf("\n"); 
}

SLTNode* SLTNodeFind(SLTNode* pphead, SLTDataType x)
 

SLTNode* SLTNodeFind(SLTNode* pphead, SLTDataType x)
{
	SLTNode* cur = pphead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL; //Can't find
}

Find a data in a single linked list

SLTNode* SLTNodeFind(SLTNode* pphead, SLTDataType x)
{
     SLTNode* cur = pphead;// A pointer is used to represent the head node to avoid arbitrary change of the head node
     While (cur! = null) / / stop when cur is empty, indicating that the data of the node that is not empty has been judged
    {
         If (cur - > data = = x) / / when the data to be searched is found
        {
            return cur;
        }
        cur = cur->next;
    }
     return NULL; // Can't find
}

void SLTNodeInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) 

void SLTNodeInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) //It is not the data change of pos position, and there is no need to transfer the secondary pointer
{
	assert(pphead);
	assert(pos);
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == pos)
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;
	}
}

Insert a data before the pos position

void SLTNodeInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) / / not for pos position     If the data is changed, there is no need to transfer the secondary pointer
{
    assert(pphead);
     assert(pos); // Judge that the value passed from POS is not a valid value
     SLTNode* newnode = BuyListNode(x);// Open up new nodes
     if (*pphead == pos) / / when the first node is pos
    {
        newnode->next = *pphead; 
        *pphead = newnode;
    }
    else
    {
        SLTNode* prev = *pphead;
         While (prev - > next! = pos) / / stop when the next node of pos is pos,
        {
            prev = prev->next;
        }
         prev->next = newnode;// At this time, prev records the previous node of pos, and the next node of prev points to the new node
         newnode->next = pos;// The next node of the new node points to POS
    }
}

void SLTNodeErase(SLTNode** pphead, SLTNode* pos)

void SLTNodeErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if (*pphead == pos)
	{
		SLTNodePopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

Delete the node at pos position in the single linked list

void SLTNodeErase(SLTNode** pphead, SLTNode* pos)
{
    assert(pphead);
     assert(*pphead);// Judge whether the first node is empty. If it is empty, there will be no node and it cannot be deleted
     assert(pos); // Judge that the value passed from POS is not a valid value
     if (*pphead == pos) / / when the pos value is the header node, it is equivalent to header deletion
    {
         SLTNodePopFront(pphead); // Header deletion
    }
     else / / when pos does not point to the first node
    {
         SLTNode* prev = *pphead;// Record the previous node of pos, so that the front and rear nodes can be connected
         While (prev - > next! = pos) / / prev event pos ends at the previous node
        {
            prev = prev->next;
        }
         prev->next = pos->next; // POS previous node POS next node
         free(pos);// Release the POS node, so that the node at the POS position is deleted and the front and rear linked lists are connected
        pos = NULL;
    }
}

Single linked list complete code

SList.h

#define  _CRT_SECURE_NO_WARNINGS 1
#pragma once

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

typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

//void SLTNodeInit(SLTNode** ps);  // The single linked list does not need to be initialized
//Destruction of single linked list
void SLTNodeDestroy(SLTNode** pphead);
//Tail insertion
void SLTNodePushBack(SLTNode** pphead, SLTDataType x);
//Tail deletion
void SLTNodePopBack(SLTNode** pphead);
//Head insert
void SLTNodePushFront(SLTNode** pphead, SLTDataType x);
//Header deletion
void SLTNodePopFront(SLTNode** pphead);
//Print single linked list
void SLTNodePrint(SLTNode* pphead);
//Find a data in the single linked list and return the address
SLTNode* SLTNodeFind(SLTNode* pphead, SLTDataType x);
//Insert a data before pos
void SLTNodeInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x); //It is not the data change of pos position, and there is no need to transfer the secondary pointer
//Delete pos location data
void SLTNodeErase(SLTNode** pphead, SLTNode* pos);

SList.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"

void SLTNodeDestroy(SLTNode** pphead)
{
	SLTNode* cur = *pphead;
	while (cur != NULL)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = NULL;
		cur = next;
	}
}

SLTNode* BuyListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	else
	{
		newnode->data = x;
		newnode->next = NULL;
	}
	return newnode;
}

void SLTNodePushBack(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		//Find tail node
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

void SLTNodePopBack(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	if ((*pphead)->next == NULL)
	{
		SLTNode* cur = *pphead;
		free(cur);
		cur = NULL;
	}
	else
	{
		SLTNode* prev = NULL;
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;
		prev->next = NULL;
	}
}

void SLTNodePushFront(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
}

void SLTNodePopFront(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* next = (*pphead)->next;
		free(*pphead);
		*pphead = next;
	}
}

void SLTNodePrint(SLTNode* pphead)
{
	SLTNode* cur = pphead;
	while (cur!= NULL)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

SLTNode* SLTNodeFind(SLTNode* pphead, SLTDataType x)
{
	SLTNode* cur = pphead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL; //Can't find
}

void SLTNodeInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) //It is not the data change of pos position, and there is no need to transfer the secondary pointer
{
	assert(pphead);
	assert(pos);
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == pos)
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;
	}
}

void SLTNodeErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if (*pphead == pos)
	{
		SLTNodePopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

Code test.c

#define  _CRT_SECURE_NO_WARNINGS 1

#include"SList.h"
void Test1()
{
	SLTNode* plist = NULL;
	SLTNodePushBack(&plist, 1);
	SLTNodePushBack(&plist, 2);
	SLTNodePushBack(&plist, 3);
	SLTNodePushBack(&plist, 4);
	SLTNodePushBack(&plist, 3);
	SLTNodePushBack(&plist, 3);

	SLTNodePopBack(&plist);

	//SLTNodePopFront(&plist);

	SLTNodePushFront(&plist, 10);
	SLTNodePushFront(&plist, 20);

	SLTNode* pos = SLTNodeFind(plist, 10); //No address
	if (pos == NULL)
	{
		printf("Can't find\n");
	}
	else
	{
		SLTNodeInsert(&plist, pos, 100);
	}

	pos = SLTNodeFind(plist, 3);
	//int i = 1;
	//while (pos)
	//{
	//	printf("address of the% d data to be searched:% P \ n", I, & (pos - > data));
	//	i++;
	//	pos = SLTNodeFind(pos->next, 3);
	//}
	if(pos!=NULL)
	SLTNodeErase(&plist, pos);

	SLTNodePrint(plist);
	SLTNodeDestroy(&plist);
	plist = NULL;
}
int main()
{
	Test1();
	return 0;
}

The test results are as follows:

Topics: data structure linked list