静的リンク リストの概要
静的リンク リストも線形ストレージ構造の一種です。シーケンシャル リストとリンク リストの利点を考慮しています。たとえば、線形リストを構築する操作には、大きな領域を事前に割り当てる必要があります。各ノードには要素の値が格納されます。ポインタの代わりにカーソルを使用し、配列内のノードの相対位置を指定します。
線形リストで操作を挿入および削除するときに要素を移動する必要はなく、ポインターの値を変更するだけで済むため、チェーン構造の利点があります。
たとえば、静的リンク リストを使用して {1,2,3} を格納するプロセスは次のとおりです。
(1) 図に示すように、サイズを 6 として、十分な大きさの配列を作成します。
(2) 格納するとき各データ要素には、配列内の各要素のすぐ後続要素の位置インデックスを示すために使用される整数変数が装備されています。
静的リンクリストの構築
(1) 静的リンクリストのノード構築
typedef struct
{
ElemType data;
int cur;
} Component,StaticLinkList[MAXSIZE];
1 つの領域 (data) は実際のデータを格納するために使用され、
もう 1 つの領域 (cur) は「指す」次のデータ領域配列の添字を格納するために使用されます (ここでの指すことはポインタを指しません)。 Cursor と呼ばれ、配列の添字を格納します (格納規則に関係なく、格納されるのは配列の添字です)。配列
内の要素 (最初と最後を除く) は、それらが使用されているかどうかに応じて分類できます。 2 つのタイプ (上の赤と緑のように) があり、これら 2 種類の要素はそれぞれチェーンを形成できます。未使用のチェーンをバックアップ チェーンと呼ぶことができます。
配列内の最初の要素 (添字 0) と最後の要素 (添字 n-1) にはデータが格納されません。最初の要素の cur にはバックアップ チェーンの最初の要素の添字が格納され、最後の要素 Cur にはバックアップ チェーンの最初の要素の添字が格納されます。リンクされたリストの最初の要素の添え字。たとえば、上の図の最後の要素の cur は 1 で、1 は最初の赤いボックスの添字です。
(2) 静的リンクリストの実装
データ リンク リストが初期化される前は、配列内のすべての位置が空いているため、スタンバイ リンク リストにリンクする必要があります。
コードは次のとおりです。
Status InitList(StaticLinkList space) //初始化静态链表
{
for (int i = 0; i < MAXSIZE - 1; i++)
space[i].cur = i + 1;
space[MAXSIZE - 1].cur = 0;
return OK;
}
静的リンク リストにデータを追加する場合、新しいデータに使用できるようにするために、事前にスタンバイ リンク リストからノードを削除する必要があります。
スタンバイ リンク リストからノードを削除する最も簡単な方法は、a[0] の直接の後続ノードを削除することです。同様に、スタンバイ リンク リストにアイドル ノードを追加すると、新しい直接後続ノードが a[0] に追加されます。a[0] はスタンバイ リンク リストの最初のノードであるため、その位置がわかっており、スタンバイ リンク リストを横断せずにその直接の後続ノードを操作することは比較的簡単で、時間計算量は O(1) です。
静的リンク リストに要素 1 を追加するプロセスは図に示すとおりです。
リンク リストの挿入操作は線形リストのような要素のシフト操作を必要とせず、ポインタが指す位置を変更するだけで完了します。挿入。
(1) まず、バックアップ チェーンの最初の要素の添え字 j を見つけて、それに値を割り当てます。
(2) 挿入位置を i とし、i が連結リストの範囲に属するかどうかを判定し、属する場合には先頭からたどって添字 i-1 の要素位置を探します。
(3) j の cur を i-1 の cur に代入し、i-1 の cur を j に等しく設定して挿入作業は完了です。実際、これは動的リンク リストの挿入操作であり、原理は同じです。
Status ListInsert(StaticLinkList space, int i, Elemtype e) //插入元素
{
int j,k,l;
k = MAXSIZE - 1;
if (i<1 || i>ListLength(space) + 1)
return ERROR;
j = Malloc_SSL(space);
if (j)
{
space[j].data = e;
for (l = 1; l <= i - 1; l++)
k = space[k].cur;
space[j].cur = space[k].cur;
space[k].cur = j;
return OK;
}
else
return ERROR;
}
静的リンク リストから指定した要素を削除するには、次の 2 つの手順を実行するだけで済みます:
ターゲット要素を含むノードをデータ リンク リストから削除し、
削除したノードを次回再利用できるようにスタンバイ リンク リストに追加します。
Status ListDelete(StaticLinkList space, int i) //删除元素
{
int j, k, l;
k = MAXSIZE - 1;
if (i<1 || i>ListLength(space))
return ERROR;
for (j = 1; j <= i - 1; j++)
k = space[k].cur;
j = space[k].cur;
space[k].cur = space[j].cur;
Free_SSL(space, j);
return OK;
}
完全なコードは次のとおりです。
#include <string.h>
#include <stdio.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 1000
typedef int Status;
typedef char Elemtype;
Status visit(Elemtype c) //访问元素
{
printf("%c", c);
return OK;
}
typedef struct //构建结构体
{
Elemtype data;
int cur;
}Component, StaticLinkList[MAXSIZE];
Status InitList(StaticLinkList space) //初始化静态链表
{
for (int i = 0; i < MAXSIZE - 1; i++)
space[i].cur = i + 1;
space[MAXSIZE - 1].cur = 0;
return OK;
}
int Malloc_SSL(StaticLinkList space) //返回备用链表的第一个元素的地址并将space[0].cur指向该元素
{
int i = space[0].cur;
if (space[0].cur)
space[0].cur = space[i].cur;
return i;
}
void Free_SSL(StaticLinkList space,int k) //将元素放回备用链表中的首位
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
int ListLength(StaticLinkList space) //返回链表的长度
{
int j = 0;
int i = space[MAXSIZE - 1].cur;
while (i)
{
i = space[i].cur;
j++;
}
return j;
}
Status ListInsert(StaticLinkList space, int i, Elemtype e) //插入元素
{
int j,k,l;
k = MAXSIZE - 1;
if (i<1 || i>ListLength(space) + 1)
return ERROR;
j = Malloc_SSL(space);
if (j)
{
space[j].data = e;
for (l = 1; l <= i - 1; l++)
k = space[k].cur;
space[j].cur = space[k].cur;
space[k].cur = j;
return OK;
}
else
return ERROR;
}
Status ListDelete(StaticLinkList space, int i) //删除元素
{
int j, k, l;
k = MAXSIZE - 1;
if (i<1 || i>ListLength(space))
return ERROR;
for (j = 1; j <= i - 1; j++)
k = space[k].cur;
j = space[k].cur;
space[k].cur = space[j].cur;
Free_SSL(space, j);
return OK;
}
Status ListTraverse(StaticLinkList space) //打印元素值
{
int j = 0;
int i = space[MAXSIZE - 1].cur;
while (i)
{
visit(space[i].data);
i = space[i].cur;
j++;
}
return j;
printf("\n");
}
int main(void)
{
StaticLinkList L;
int i = 0;
i = InitList(L);
printf("初始化L后长度为:%d\n", ListLength(L));
i = ListInsert(L, 1, 'F');
i = ListInsert(L, 1, 'E');
i = ListInsert(L, 1, 'D');
i = ListInsert(L, 1, 'B');
i = ListInsert(L, 1, 'A');
printf("插入后静态链表为:\n");
ListTraverse(L);
i = ListInsert(L, 3, 'C');
printf("\n在B与D之间插入c后的静态链表为:\n");
ListTraverse(L);
i = ListDelete(L, 1);
printf("\n在删除A后其为:\n");
ListTraverse(L);
printf("\n");
getchar();
return i;
}
結果を以下に示します