序章
意味
★★★シングルリンクリストとは、線形リストを連鎖的にアクセスするためのデータ構造であり、任意のアドレスを持つ記憶装置群を用いて線形リスト内のデータを格納します。
原理
<1> リンクリスト内のデータはノードと、データフィールド+ポインタフィールドのノード構成で表現されます。
<2> データフィールドはデータを格納する記憶単位であり、ポインタフィールドは次のノードのアドレスです。
アドバンテージ
<1> 単一リンクリストが要素を挿入または削除する場合、その先行要素と挿入または削除された要素のポインタを変更するだけで済みます。
<2> 保存データ量が不明な場合、一重リンクリストは保存データごとにスペースを空けるので、スペースがよく把握でき、無駄が目立ちにくい。
欠点がある
<1> シングルリンクリストはランダムアクセスをサポートしていないため、検索効率が遅くなります。
<2> アクセスするデータの数がわかっている場合、単結合リストの各データにはポインタフィールドも含まれるため、スペースの無駄が大きくなります。さらに、シングルリンクリストの場合、各データアドレスがランダムに開かれるため、記憶領域が断片化され、小さな断片化された領域が多数存在します。
比較
単一リンク リストとシーケンシャル リストを比較するには、以下のリンクをクリックして前の記事を参照してください。
リンク: ★★★リンク。
時間内に
<1> シーケンス テーブルの構造は配列のようなもので、添字によって要素にアクセスできるため、シーケンス テーブルのデータはランダム アクセスをサポートしますが、単一リンク リストのデータはチェーンに格納されます。要素はランダム アクセスをサポートしていないため、要素を知りたい場合は、要素が見つかるまでヘッド ノードからリンク リスト全体をたどることしかできません。したがって、逐次リスト内のランダム要素にアクセスする時間計算量は O(1) であり、単一リンク リスト内のランダム要素にアクセスする平均時間計算量は O(n) です。
<2> 順序表の要素は連続して格納されているため、特定の位置の要素を挿入または削除するには、それ以降のすべての要素を1要素分前後に移動する必要があり、時間がかかります。単一のリンク リストが挿入または削除されます。要素を削除する場合は、その先行要素と、挿入または削除された要素の方向を変更するだけで済みます。したがって、逐次リスト内のランダムな位置での要素の挿入と削除の平均時間計算量は O(n) であり、単一リンク リスト内のランダムな位置での要素の挿入と削除の時間計算量は O(1) です。
宇宙で
<1> シーケンス テーブルの空間は通常連続的に解放され、複数の要素を格納するための空間が一度に解放されるため、シーケンス テーブルを使用すると、複数のデータを一度にキャッシュに書き込むことができ、その後、シーケンス テーブルであるメイン メモリに書き込まれます。CPU キャッシュはより効率的であり、CPU パイプラインが常に中断されるわけではありません。また、単一リンク リストは、データを保存する必要があるたびにスペースを空けるだけであるため、各データ ストレージは個別にキャッシュ領域に書き込んでからメインメモリに書き込むと、シングルリンクリストの CPU キャッシュ効率が低くなり、CPU パイプラインが頻繁に中断されます。
<2> データ量がわかっているかどうかは、単結合リストと逐次リストの選択と使用にも影響します。この観点は、上記の長所と短所を考慮して述べることができます。
実験の過程と結果
コード
//<库函数>
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<math.h>
//<相关参数的宏定义>
#define Len sizeof(Node)
typedef int Elemtype;
typedef struct Node
{
Elemtype data;
struct Node* next;
}Node;
typedef struct Node Linklist;
//<单链表的初始化、增删查改、输出函数的定义>
Linklist* Creat_L();
void Out_Linklist(Linklist *h);
void Insert_List(Linklist *L,int i,Elemtype x);
void Delete_List(Linklist *L,int i);
void Found_List(Linklist *L,Elemtype x);
void Amend_List(Linklist *L,int i,Elemtype x);
// <主函数>
void main()
{
Linklist *L;
int k ;
int i ;
Elemtype x;
printf(" 《 Welcome to use the founction 》\n");
printf(" The founction can offer following service\n");
printf(" *******Please first Initlist*******\n\n");
printf(" 1、Initlist ->初始化单链表\n");
printf(" 2、Insertlist ->插入操作\n");
printf(" 3、Deletelist ->删除操作\n");
printf(" 4、Foundlist ->查找操作\n");
printf(" 5、Amendlist ->更改操作\n");
printf(" 0、Exitlist ->退出操作\n\n\n");
printf(" Please choose following digital:1、2、3、4、5、0\n");
printf(" Finish your idea!!!!!!\n");
do
{
printf("\n\nPlease Input your choice:");
scanf("%d",&k);
switch(k)
{
case 1:
{
L = Creat_L();
Out_Linklist(L);
}break;
case 2:
{
printf("Input the position of Insert:");
scanf("%d",&i);
printf("Input the data of Insert:");
scanf("%d",&x);
Insert_List(L,i,x);
Out_Linklist(L);
}break;
case 3:
{
printf("Input the position of Delete:");
scanf("%d",&i);
Delete_List(L,i);
Out_Linklist(L);
}break;
case 4:
{
printf("Input the data of Found:");
scanf("%d",&x);
Found_List(L,x);
//Out_Linklist(L);
}break;
case 5:
{
printf("Input the position of Amend:");
scanf("%d",&i);
printf("Amend data to:");
scanf("%d",&x);
Amend_List(L,i,x);
Out_Linklist(L);
}break;
}
}while(k!=0);
}
// <初始化函数>
Linklist* Creat_L()
{
//int i;
Linklist *h,*p,*s;
Elemtype x;
h = (Node*)malloc(Len);
h->next = NULL;
p = h;
printf("Please Enter the FIRST Node data: ");
scanf("%d",&x);
while(x!=99) //假设终止条件
{
s = (Node*)malloc(Len);
s->data = x; //赋值
s->next = NULL;
p->next = s;
p = s;
printf("Please Enter the NEXT Node data: ");
scanf("%d",&x);
}
return h;
}
//<输出函数>
void Out_Linklist(Linklist *h)
{
Linklist *p;
p = h->next;
printf("Output Linklist:");
while(p)
{
if(p->next!=NULL)
{
printf("%d -> ",p->data);
p = p->next;
}
else
{
printf("%d",p->data);
p = p->next;
}
}
}
//<插入函数>
void Insert_List(Linklist *L,int i,Elemtype x)
{
int j;
Linklist *p,*s;
p = L;
if(i<0)
{
printf("The position is unreasonable!!!!!!!!!\n");
printf("Please Input Again!!!!!!!\n");
exit(0);
}
for(j=0;j<=i;j++)
{
if(j == i)
{
s = (Node*)malloc(Len); //声明一个新节点 s ,并填充相关数据,插入链表
s->data = x;
s->next = p->next;
p->next = s;
break;
}
p = p->next;
}
}
// <删除函数>
void Delete_List(Linklist *L,int i)
{
Linklist *p,*s;
int j;
Elemtype x;
p = L;
if(i<0||p->next == NULL)
{
printf("The position is unreasonable!!!!!!!!!\n");
printf("Please Input Again!!!!!!!\n");
exit(0);
}
for(j=0;j<=i;j++)
{
if(j==i)
{
s = p->next; //定义变量 s 指向牺牲节点,并释放
x = s->data;
p->next = s->next;
free(s);
}
p = p->next;
}
}
// <查找函数>
void Found_List(Linklist *L,Elemtype x)
{
Linklist *p;
int i = 0;
p = L;
while(p)
{
if(p->data == x)
{
printf("Found data in %d position\n",i);
break;
}
else
{
i++;
p = p->next;
}
}
if(p==NULL)
printf("Sorry , The data is not in the Linklist!!!!!!\n");
}
//<修改函数>
void Amend_List(Linklist *L,int i,Elemtype x)
{
Linklist *p;
int j = 0;
p = L;
while(p)
{
if(j == i)
{
p->data = x;
break;
}
else
{
j++;
p = p->next;
}
}
if(p==NULL)
printf("The position of inputting is incorrect!!!!!!\n");
}
演算結果
★★★初期化、追加、削除、確認、修正の基本操作が順番に完了します★★★
要約する
以上をまとめると、逐次リストと単結合リストにはそれぞれ長所と短所があり、どちらを使用するのが良いかは具体的な問題によって異なるため一概には言えません。