単一リンクリストの追加、削除、チェック、および変更の図から始めましょう。
まずはリンクリストをご紹介します。
リンク リストとは、各構造にデータと構造ポインタが含まれていることを意味します。このポインタは次の構造をロックするチェーンのように機能しますが、各構造の空間は比較的独立しています。
図:
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 つずつ示しません。 (これまでのテストでは問題は発生していません)