単一リンクリストの詳細な説明 (最後に図と完全なソースコード付き)

単一リンクリストの追加、削除、チェック、および変更の図から始めましょう。

まずはリンクリストをご紹介します。

リンク リストとは、各構造にデータと構造ポインタが含まれていることを意味します。このポインタは次の構造をロックするチェーンのように機能しますが、各構造の空間は比較的独立しています。

図:

1 最初にテール挿入を実装します

終端を挿入したい場合は、終端ノードを見つけて、次のポインタを使用して接続する必要があります。

図:

以下はコードの実装です

ここでは特殊なケースを考えました。つまり、リンクされたリストが空の場合、ヘッド ノードを直接接続します。

最初のノードが空かどうかを判断するには、ここで 2 次ポインターを使用する必要があります。

(一次ポインターを使用する場合、この関数のスコープを離れた後に空間は破棄されます。これは、作業が無駄になることと同じです)

スペースを使用するたびに忘れずにスペースを解放してください。そうしないと、メモリ リークが発生します。

SL* BuyNewnode(DataSL x)
{
	SL* Newnode = (SL*)malloc(sizeof(SL));
	if (Newnode==NULL)
	{
		perror("malloc");
		assert(Newnode);
	}
	Newnode->data = x;
	Newnode->next = NULL;
	return Newnode;
}


void DistorySL(SL** pphead)
{
    SL* tail = *pphead;
	if (tail)
		return;
	else
	{
		while (tail->next)
		{
			SL* cur = tail->next;
			tail->next = NULL;
			tail->data = 0;
			free(tail);
			tail = cur;
		}
		tail->next = NULL;
		tail->data = 0;
		free(tail);
	}
}


void BackPushSL(SL** pphead, DataSL x)//尾插
{
	SL* tail = *pphead;
	SL* Newnode = BuyNewnode(x);
	if (tail == NULL)
	{
		*pphead = Newnode;
	}
	else
	{
		while (tail->next)
		{
			tail = tail->next;
		}
		tail->next = Newnode;
	}
}

2 次に末尾の削除を実装します

void BackPopSL(SL** pphead)//尾删
{
	assert(pphead);
	assert(*pphead);//空链表不删
	SL* tail = *pphead;
	if (tail->next==NULL)
	{
		tail->data = 0;
		free(tail);
	}
	else
	{
		while (tail->next->next)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}

3 次にヘッドプラグを実装します

void FrontPushSL(SL** pphead, DataSL x)
{
	assert(pphead);
	SL* tail = *pphead;
	SL* Newnode= BuyNewnode(x);
	if (tail == NULL)
	{
		tail = BuyNewnode(x);
	}
	else
	{
		Newnode->next = tail;
	}
	*pphead = Newnode;
}

4 次にヘッダーの削除を実装します

void FrontPopSL(SL** pphead)
{
	assert(pphead);
	SL* tail = (*pphead)->next;
	free(*pphead);
	(*pphead)->next = NULL;
	*pphead = tail;
}

5 次に、中間挿入(協調検索)を実装します。

中挿入には、前挿入と後挿入の2つの場合がある。

SL* FindSL(SL** pphead, DataSL x)
{
	SL* tail = *pphead;
	while (tail)
	{
		if (tail->data == x)
		{
			break;
		}
		else
		{
			tail = tail->next;
		}
	}
	return tail;
}


void FrontInsertSL(SL** pphead,SL* pos,DataSL x)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	SL* Newnode = BuyNewnode(x);
	SL* cur = tail;
	if (*pphead == NULL)
	{
		FrontPushSL(&tail,x);
	}
	while (tail!= pos)
	{
		cur = tail;
		tail = tail->next;
	}
	cur->next = BuyNewnode(x);
	cur->next->next = pos;
}

背面挿入の状況も同様

SL* FindSL(SL** pphead, DataSL x)
{
	SL* tail = *pphead;
	while (tail)
	{
		if (tail->data == x)
		{
			break;
		}
		else
		{
			tail = tail->next;
		}
	}
	return tail;
}



void AfterInsertSL(SL** pphead, SL* pos, DataSL x)
{
	assert(pphead);
	assert(pos);
	SL* Newnode = BuyNewnode(x);
	SL* tail = *pphead;
	while (tail != pos)
	{
		tail = tail->next;
	}
	SL* cur = tail->next;
	tail->next = Newnode;
	Newnode->next = cur;
}

6 次に、ノードのチェックと削除を実装します (原理は上記と同様で、自分で絵を描くことができます)

void EraseSL(SL** pphead, SL* pos)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	if (tail==pos)
	{
		BackPopSL(tail);
	}
	else
	{
		while (tail->next != pos)
		{
			tail = tail->next;
		}
	SL* cur = tail->next;
	tail->next = tail->next->next;
	cur->data = 0;
	cur->next = NULL;
	free(cur->next);
	}
}

7 最後に、ノードの内容を変更します

void ReviseSL(SL** pphead, SL* pos, DataSL x)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	if (tail== pos)
	{
		tail->data = x;
	}
	else
	{
		while (tail->next != pos)
		{
			tail = tail->next;
		}
		tail->next->data = x;
	}
}

以下にすべてのソースコードを添付します

SingleSeqList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataSL;
typedef struct SingleSqList SL;
typedef struct SingleSqList 
{
	DataSL data;
	SL* next;
}SL;

//开辟节点
SL* BuyNewnode(DataSL x);
//打印单链表的值
void SLPrint(SL* pphead);
//销毁链表
void DistorySL(SL** pphead);

singleSeqList.h

//对链表的增删查改
//头插尾插,头删尾删
void BackPushSL(SL** pphead,DataSL x);
void BackPopSL(SL** pphead);

void FrontPopSL(SL** pphead);
void FrontPushSL(SL** pphead, DataSL x);

//前插
void FrontInsertSL(SL** pphead,SL* pos,DataSL x);


//后插
void AfterInsertSL(SL** pphead, SL* pos, DataSL x);



//查找节点
SL* FindSL(SL** pphead, DataSL x);

//删除某个节点
void EraseSL(SL** pphead, SL* pos);

//修改某个节点的内容
void ReviseSL(SL** pphead, SL* pos, DataSL x);


SingleSeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SingleSqList.h"


void SLPrint(SL** pphead)
{
	SL* tail = *pphead;
	if (tail == NULL)
	{
		return;
	}
	while (tail->next)
	{
		printf("%d->", tail->data);
		tail = tail->next;
	}
	printf("%d", tail->data);
}

void DistorySL(SL** pphead)
{
    SL* tail = *pphead;
	if (tail)
		return;
	else
	{
		while (tail->next)
		{
			SL* cur = tail->next;
			tail->next = NULL;
			tail->data = 0;
			free(tail);
			tail = cur;
		}
		tail->next = NULL;
		tail->data = 0;
		free(tail);
	}
}




SL* BuyNewnode(DataSL x)
{
	SL* Newnode = (SL*)malloc(sizeof(SL));
	if (Newnode==NULL)
	{
		perror("malloc");
		assert(Newnode);
	}
	Newnode->data = x;
	Newnode->next = NULL;
	return Newnode;
}


void BackPushSL(SL** pphead, DataSL x)//尾插
{
	assert(pphead);
	SL* tail = *pphead;
	SL* Newnode = BuyNewnode(x);
	if (tail == NULL)
	{
		*pphead = Newnode;
	}
	else
	{
		while (tail->next)
		{
			tail = tail->next;
		}
		tail->next = Newnode;
	}
}


void BackPopSL(SL** pphead)//尾删
{
	assert(pphead);
	assert(*pphead);//空链表不删
	SL* tail = *pphead;
	if (tail->next==NULL)
	{
		tail->data = 0;
		free(tail);
	}
	else
	{
		while (tail->next->next)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}

void FrontPushSL(SL** pphead, DataSL x)
{
	assert(pphead);
	SL* tail = *pphead;
	SL* Newnode= BuyNewnode(x);
	if (tail == NULL)
	{
		tail = BuyNewnode(x);
	}
	else
	{
		Newnode->next = tail;
	}
	*pphead = Newnode;
}


void FrontPopSL(SL** pphead)
{
	assert(pphead);
	SL* tail = (*pphead)->next;
	free(*pphead);
	(*pphead)->next = NULL;
	*pphead = tail;
}


SL* FindSL(SL** pphead, DataSL x)
{
	SL* tail = *pphead;
	while (tail)
	{
		if (tail->data == x)
		{
			break;
		}
		else
		{
			tail = tail->next;
		}
	}
	return tail;
}



void FrontInsertSL(SL** pphead,SL* pos,DataSL x)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	SL* Newnode = BuyNewnode(x);
	SL* cur = tail;
	if (*pphead == NULL)
	{
		FrontPushSL(&tail,x);
	}
	while (tail!= pos)
	{
		cur = tail;
		tail = tail->next;
	}
	cur->next = BuyNewnode(x);
	cur->next->next = pos;
}

void AfterInsertSL(SL** pphead, SL* pos, DataSL x)
{
	assert(pphead);
	assert(pos);
	SL* Newnode = BuyNewnode(x);
	SL* tail = *pphead;
	while (tail != pos)
	{
		tail = tail->next;
	}
	SL* cur = tail->next;
	tail->next = Newnode;
	Newnode->next = cur;
}


void EraseSL(SL** pphead, SL* pos)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	if (tail==pos)
	{
		BackPopSL(tail);
	}
	else
	{
		while (tail->next != pos)
		{
			tail = tail->next;
		}
	SL* cur = tail->next;
	tail->next = tail->next->next;
	cur->data = 0;
	cur->next = NULL;
	free(cur->next);
	}
}


void ReviseSL(SL** pphead, SL* pos, DataSL x)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	if (tail== pos)
	{
		tail->data = x;
	}
	else
	{
		while (tail->next != pos)
		{
			tail = tail->next;
		}
		tail->next->data = x;
	}
}


基本的にリンク リストのすべての関数を実装したので、ここでは 1 つずつ示しません。 (これまでのテストでは問題は発生していません)

おすすめ

転載: blog.csdn.net/2301_79811170/article/details/135038840