Singly linked list knowledge points

Table of contents

1.1 The concept and structure of linked list

1.2 Classification of linked lists

1.3 Implementation of linked list


Things you don’t know, things that you find rare, don’t hide them, first figure out and then master.


1.1 The concept and structure of linked list

  The linked list is a discontinuous and non-sequential storage structure in the physical storage structure. The logical order of the data elements is realized by the link of the pointers in the linked list . (Addresses are not necessarily continuous)

1.2 Classification of linked lists

(1) One-way or two-way

(2) To take the lead or not to take the lead

(3) Cyclic or acyclic

1.3 Implementation of linked list

One-way, headless, no loop

SList.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>


typedef int SLTDateType;

//单链表中,定义一个结构体,结构体里面有两个结构体成员,一个是数据,一个是指针(指针指向一个结构体),
// 这个指针的类型是一个结构体,这个结构体又和自己类型一样,所以结构体有的自引用
typedef struct SListNode
{
	SLTDateType date;//数据
	struct SListNode* next;//储存下一个节点的地址
}SListNode;
//知识点结构体的自引用方式

//单链表不需要初始化,因为单链表刚开始只有一个指针
void SListPrint(SListNode* phead);//打印
//尾插
void SListPushBack(SListNode** pphead, SLTDateType x);
//头插
void SListPushFront(SListNode** pphead, SLTDateType x);
//尾删
void SListPopBack(SListNode** pphead);//需要传递的是头部结构体的地址的地址,当尾删的时候,如果单链表就有一个值,那么进行尾删的时候,需要改变头部结构体地址
//头删
void SListPopFront(SListNode** pphead);
//查找
SListNode* SListFind(SListNode* phead, SLTDateType x);
//前插入
void SListInsert(SListNode** pphead, SListNode* pos, SLTDateType x);
//后插入
void SListInsertAfter(SListNode* pos, SLTDateType x);
//删除
void SListErase(SListNode** pphead, SListNode* pos);
//删除后面
void SListEraseAfter(SListNode** pphead);
//销毁
void SListDestory(SListNode** pphead);

SList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"


//打印
void SListPrint(SListNode* phead)
{
	//assert(phead);//这里不需要断言,因为单链表可能是空链表
	SListNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->date);
		cur = cur->next;
	}
	printf("NULL\n");
}

//一个节点的创建
SListNode* BuySListNode(SLTDateType x)
{
	SListNode* newnode = (SListNode*)malloc(sizeof(SLTDateType));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	else
	{
		newnode->date = x;
		newnode->next = NULL;
	}
	return newnode;
}

//尾插
void SListPushBack(SListNode** pphead, SLTDateType x)//当链表是空的时候,尾插,相当于头插,需要改变头部的地址,改变地址,需要传递头部地址的地址【形参的改变不影响实参】
//需要改变谁,就需要传谁的地址
{
	assert(pphead);
	SListNode* newnode = BuySListNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SListNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}
//头插//改变头部地址就需要传二级指针
void SListPushFront(SListNode** pphead, SLTDateType x)
{
	assert(pphead);
	SListNode* newnode = BuySListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}


//尾删//要把倒数第二个值的next变成NULL,所以需要倒数第二个结构体的地址,才能改变(形参的改变,不改变实参)【每一个结构体,相当于结构体传参】
//没有节点,一个节点,许多节点
void SListPopBack(SListNode** pphead)
{
	assert(pphead);
	if (*pphead == NULL)//空
	{
		return;
	}
	else if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SListNode* prev = NULL;
		SListNode* tail = *pphead;
		while (tail->next != NULL)
		{
			prev = tail;//倒数第二个
			tail = tail->next;//倒数第一个
		}
		free(tail);
		tail = NULL;
		prev->next = NULL;
	}
}
//头删
void SListPopFront(SListNode** pphead)
{
	assert(pphead);
	if (*pphead == NULL)
	{
		return;
	}
	else//一个值和很多值
	{
		SListNode* front = NULL;
		front = (*pphead)->next;
		free(*pphead);
		*pphead = front;
	}
}

//查找
SListNode* SListFind(SListNode* phead, SLTDateType x)
{
	SListNode* cur = phead;
	while (cur != NULL)
	{
		if (cur->date == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//插入,在某个数字前插入//首先用find找某个数的地址,然后再在地址处插入。,
void SListInsert(SListNode** pphead, SListNode* pos, SLTDateType x)
{
	assert(pphead);
	assert(pos);
	if (*pphead == pos)
	{
		SListPushFront(pphead, x);
	}
	else
	{
		SListNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		SListNode* newnode = BuySListNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}
//在insert之后插入
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
	assert(pos);
	SListNode* next = pos->next;
	SListNode* newnode = BuySListNode(x);
	pos->next = newnode;
	newnode->next = next;
}

//删除
void SListErase(SListNode** pphead, SListNode* pos)
{
	assert(pphead);
	assert(pos);
	if (*pphead == pos)
	{
		SListPopFront(pphead);
	}
	else
	{
		SListNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		pos = NULL;
		free(pos);
	}
}

//删除后面
void SListEraseAfter(SListNode* pos)
{
	assert(pos);
	if (pos->next == NULL)
	{
		return;
	}
	else
	{
		SListNode* next = pos->next;
		pos->next = next->next;
		free(next);
		next = NULL;
	}
}

//销毁
void SListDestory(SListNode** pphead)
{
	assert(pphead);
	SListNode* cur = *pphead;
	SListNode* next = NULL;
	while (cur->next != NULL)
	{
		next = cur->next;
		free(cur);
		cur = NULL;
	}
	*pphead = NULL;
}


The single-linked list first defines a pointer to a structure, and does not require structure initialization; but the sequence table first defines a structure, which requires structure initialization. (When the sequence table is initialized, the value is empty, but the capacity and size are available) (Single-linked list, when there is no value, the structure pointer (head address) is NULL)

Guess you like

Origin blog.csdn.net/m0_57388581/article/details/131146042