単一リンクリストと関連操作の実現
学んだ知識を記録してください。間違いがありましたらご容赦ください。指摘していただければ改造いたします。それは私自身の理解で成長している恋人です。
1>単一リンクリストとは何ですか?
リニアテーブルに順次記憶は異なるが、各ノードは、データ要素を格納する(および割り当て中の連続する物理アドレスである)、及び記憶に加えて、単独でリンクされたリストを格納するデータの各ノードの次のノードへのポインタを(とし割り当てない連続した物理アドレス空間が必要)
したがって、理論的には、2つの実装は異なります
シーケンシャルテーブルの長所と短所
利点:ランダムアクセス、高いアクセス密度利点:連続したアドレス空間が不要であり、要素を移動するのに便利です
短所:連続したスペースアドレスが必要で、要素を移動するのが不便です。短所:ランダムアクセスが不可能であり、ポインタを格納するために一定のスペースが必要です。
2>単一リンクリストを定義する
typedefの意味と使用法:Typedefは、コンピュータープログラミング言語で使用され、複雑な宣言の単純なエイリアスを定義します。これは、マクロ定義とは多少異なります。それ自体は一種のストレージキーワードであり、auto、extern、mutable、static、registerなどのキーワードを同じ式に含めることはできません(データ型を再定義できます)
例:intiを割り当てます
データ型が再定義されていない場合:int i = 5
データ型を再定義した後:i = 5;
単一リンクリストはチェーンノードのテーブルであるため、そのタイプは構造体(構造体タイプ)であることがわかります。これにより、再定義を使用した後のコードの記述と効率の向上が容易になります。
typedef struct LNode //定义单链表的类型
{
int data;//每个节点存放的数据元素
struct LNode *next;//指针指向下一个节点
}LNode,*LinkList;//对struct LNode进行重命名,用LinkList去表示指向struct LNode的指针
同時に、LNode *とLinkListは同等ですが、強調されるオブジェクトは異なります。LNode*->ノード LinkList->リンクリスト(2つの意味の区別に集中できます)
3>単一リンクリスト(ヘッドノードと非ヘッドノード)を初期化します
リードノードなし
void InitList(LinkList &L)//不带头节点
{
L=NULL;//空表暂时没有数据
if(L==NULL)
{
printf("初始化成功");
}
}
L = NULLでの空のテーブルの操作は、コンピューター内のダーティデータを防ぐことです。
最初のデータノードの処理と後続のノードの処理には異なるロジックが必要であり、空のリストと空でないリストの処理にも異なるロジックが必要なため、ノードをリードしないことはコードの記述に役立ちません。
リードノード
void InitList(LinkList &L)
{
L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
if (L==NULL)//校验内存分配
{
printf("内存分配失败");
}
else {
L->next = NULL;
}
}
リンクリストの初期化は主にヘッドノードの割り当てであり、割り当ての検証に注意を払う必要があります。L-> next = NULLは、現在のテーブルにnullを指す必要があるヘッドノードが1つだけあり、ヘッドポインタがデータを格納しないためです。
4>単一リンクリストにデータを追加する
これは、テール補間を使用した単一リンクリストのデータ入力です。
アイデア:初期化後、現在の単一リンクリストは空のテーブルです->単一リンクリストは、連続したアドレス空間を持つ線形テーブルとは異なります(各データはポインターによって直接リンクされます)->データ交換のa、bと同様です
同様に、ノードの場合、ノードを使用して同様の方法でデータを保持でき、ノードは次のノードのポインタフィールドを指すことができます。前のノードへの割り当てが完了したら、次のノードに移動します。
したがって、ループの割り当てはDノードのコンテンツには影響しません。次のノードに移動したため
void CreatList(LinkList &L)//输入数据
{
LNode *P,*D;//DATA是用来保持每次输入的数据,P的作用是指向单链表尾部
L = (LNode*)malloc(sizeof(LNode));//创建头节点
L->next = NULL;//初始化单链表,一开始为空表
P = L;//空表时头节点也是尾部节点
int n;//输入数据的个数
printf("请输入数据的个数:");
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
D = (LinkList)malloc(sizeof(LNode));//给D节点开辟一个空间
printf("data[%d]=",i);
scanf("%d",&D->data);//每次输入的数据到D
D->next=P->next;//第一个节点已经填充,将移动下一个节点
P->next = D;//D代表的是一个节点,P->next是指向下一个节点
P = D;
}
}
5>単一リンクリストのデータを出力する
単一リンクリストの出力では、同じ方法でヘッドノードLを指すように新しいノードを定義する必要があります。ループ条件を使用して配列全体を出力します
void ShowList(LinkList L)
{
LNode * P;
P =(LNode*)malloc(sizeof(LNode));//分配空间
P = L->next;//单链表从P点开始遍历,等同于从头节点开始
int i = 0;//记录位序
printf("打印单链表\n");
while (P!=NULL)//只要节点不为空就可以继续输出
{
printf("data[%d]=%d\n",i,P->data);
i++;
P = P->next;
}
}
6>単一リンクリストの挿入
要素の挿入(位置順に2ノードを挿入、挿入前に3ノードを挿入)
ビット順に挿入(リードノード)
アイデア: i-1番目のノードを見つける->その後に要素を挿入します(i-1番目の要素のポインターを挿入された要素にポイントし、挿入された要素のポインターをi + 1番目の要素にポイントします)
void ListInsert(LinkList &L, int i, int e)//插入数据
{
if (i < 1)
printf("插入位置不合法");
else {
LNode *p;//用来指向查询元素的指针
int number = 0;//记录节点的位置
p = L;//查询节点应从头开始,所以指向头节点
while (p != NULL && number < i - 1)
{
p = p->next;//只是寻找到第i-1节点
number++;
}
if (p == NULL)
printf("插入位置不合法");
printf("插入位置为%d是%d\n", i, e);
LNode*s = (LNode*)malloc(sizeof(LNode));//为插入元素分配一个节点
s->data = e;//将e赋值新节点的数据域
s->next = p->next;//将插入元素的指针指向第i+1个元素
p->next = s;//将第i-1和插入元素连接
}
}
DOは使用しないでヘッドポインタあなたはので、新しいノードを再定義するために、ヘッドポインタの原因混乱と混沌のデータ・ストレージ・スペースを使用している場合、* pまでの要素ポイント照会にも、あなたが必要とするノードレコードのデータを。
LNode * s =(LNode *)malloc(sizeof(LNode))は、挿入された要素にノードを割り当て
ます
s-> data = e;新しいノードのデータフィールドにeを割り当てますs-> next = p-> next; will要素を挿入しますポインタはi +
1番目の要素を指しますp-> next = s; i-1番目の要素を挿入された要素に接続します
s-> next = p-> next;挿入された要素のポインターをi +
1番目の要素にポイントしますp-> next = s; i-1番目を挿入された要素に接続します(逆にすることはできません。sノードは■ノード)その後、背後のデータが混乱します
先頭ノードなしで要素を挿入します(ビット単位)
void ListInsert(LinkList &L, int i, int e)//无头节点插入
{
if (i < 1)
printf("插入位置不合法");
if (i == 1)//插入到头节点
{
LNode* s = (LNode*)malloc)(sizeof(LNode));//分配空间
s->data = e;//元素传递给头节点
s->next = L;//和单链表进行链接
L = s;//现在s就是头节点方便变量
}
else {
LNode *p;//用来指向查询元素的指针
int number = 0;//记录节点的位置
p = L;//查询节点应从头开始,所以指向头节点
while (p != NULL && number < i - 1)
{
p = p->next;//只是寻找到第i-1节点
number++;
}
if (p == NULL)
printf("插入位置不合法");
printf("插入位置为%d是%d\n", i, e);
LNode*s = (LNode*)malloc(sizeof(LNode));//为插入元素分配一个节点
s->data = e;//将e赋值新节点的数据域
s->next = p->next;//将插入元素的指针指向第i+1个元素
p->next = s;//将第i-1和插入元素连接
}
}
非リードノードは主に最初の位置を挿入するときに状況を考慮する必要があり、他の位置はリードノードと同じです
7>単一リンクリスト(リードノード)のデータを削除します
アイデア: i-1番目のノードを見つける->要素を削除した後(i-1番目の要素のポインターをi + 1番目の要素のデータフィールドにポイントする)、同時にi番目のスペースを解放する必要がありますノード
void ListDelet(LinkList &L, int i)
{
if (i < 1)
printf("删除位置不合法");
LNode *p;//用来指向查询元素的指针
int number = 0;//记录节点的位置
p = L;//查询节点应从头开始,所以指向头节点
while (p != NULL && number < i - 1)
{
p = p->next;//只是寻找到第i-1节点
number++;
}
if (p == NULL)
printf("删除内容为空");
LNode*q = p->next;
int e;
e = q->data;//记录删除的数据
p->next = q->next;
free(q);//释放掉该节点
printf("删除元素%d成功\n",e);
}
データの挿入と削除のポイントと同様に、i番目の要素を削除し、i-1番目のノードをi +1番目のノードに直接ポイントします。
リードノードなし
リードノードと同様に、重要な点は、最初のノードを削除するには、最初のノードの次のノードが引き続きヘッドノードとして次のノードを指す必要があるということです。
8>単一リンクリストの検索(ビット単位/値単位)
ルックアップの本質は、単一リンクリストをトラバースすることであり、トラバースされたノードの数を計算するにはカウンターが必要です。
void GetElem(LinkList L, int i)
{
if (i < 0)
printf("查询位置不合法");
else {
LNode* P;//创建一个记录节点的指针
int number = 0;//记录查询到几个节点
P = L->next;//指向头节点,从头节点开始查询变量
if (i == 0)
printf("头节点为空");//头节点不存放数据
while (P != NULL && number < i)
{
P = P->next;//寻找到第i节点
number++;
}
printf("查询第%d个元素为%d\n", i,P->data );
}
}
値で検索
void GetElem_data(LinkList L, int e)
{
LNode*P;//分配一个节点
P = L->next;
int number = 1;
while (P!=NULL&&P->data!=e)
{
P = P->next;
number++;
}
if (P = NULL)
{
printf("单链表中没有该元素");
}
else
printf("链表中有该元素位置位%d",number);
}
単一リンクリストにクエリ要素がなく、ポインタが最後のノードに移動している場合、ポイントされているポインタはNULLです。この要素がある場合、data!= eの条件は満たされず、ループがジャンプします。アウト
9>全体的なコード
vissual studio C4996エラーの場合は、プロジェクトプロパティ-> C ++前処理に_CRT_SECURE_NO_WARNINGSを追加します。
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode //定义单链表的类型
{
int data;//每个节点存放的数据元素
struct LNode *next;//指针指向下一个节点
}LNode,*LinkList;//对struct LNode进行重命名,用LinkList去表示指向struct LNode的指针
void InitList(LinkList &L)//初始化单链表
{
L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
if (L==NULL)//校验内存分配
{
printf("内存分配失败");
}
else {
L->next = NULL;
}
}
void CreatList(LinkList &L)//输入数据
{
LNode *P,*D;//DATA是用来保持每次输入的数据,P的作用是指向单链表尾部
L = (LNode*)malloc(sizeof(LNode));//创建头节点
L->next = NULL;//初始化单链表,一开始为空表
P = L;//空表时头节点也是尾部节点
int n;//输入数据的个数
printf("请输入数据的个数:");
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
D = (LinkList)malloc(sizeof(LNode));//给D节点开辟一个空间
printf("data[%d]=",i);
scanf("%d",&D->data);//每次输入的数据到D
D->next=P->next;//第一个节点已经填充,将移动下一个节点
P->next = D;//D代表的是一个节点,P->next是指向下一个节点
P = D;
}
}
void ShowList(LinkList L)
{
LNode * P;
P =(LNode*)malloc(sizeof(LNode));//分配空间
P = L->next;//单链表从P点开始遍历,等同于从头节点开始
int i = 0;//记录位序
printf("打印单链表\n");
while (P!=NULL)//只要节点不为空就可以继续输出
{
printf("data[%d]=%d\n",i,P->data);
i++;
P = P->next;
}
}
void ListInsert(LinkList &L, int i, int e)//插入数据
{
if (i < 1)
printf("插入位置不合法");
else {
LNode *p;//用来指向查询元素的指针
int number = 0;//记录节点的位置
p = L;//查询节点应从头开始,所以指向头节点
while (p != NULL && number < i - 1)
{
p = p->next;//只是寻找到第i-1节点
number++;
}
if (p == NULL)
printf("插入位置不合法");
printf("插入位置为%d是%d\n", i, e);
LNode*s = (LNode*)malloc(sizeof(LNode));//为插入元素分配一个节点
s->data = e;//将e赋值新节点的数据域
s->next = p->next;//将插入元素的指针指向第i+1个元素
p->next = s;//将第i-1和插入元素连接
}
}
void ListInsert_no(LinkList L, int i, int e)//无头节点插入
{
if (i < 1)
printf("插入位置不合法");
if (i == 1)//插入到头节点
{
LNode* s = (LNode*)malloc(sizeof(LNode));//分配空间
s->data = e;//元素传递给头节点
s->next = L;//和单链表进行链接
L = s;//现在s就是头节点方便变量
}
else {
LNode *p;//用来指向查询元素的指针
int number = 0;//记录节点的位置
p = L;//查询节点应从头开始,所以指向头节点
while (p != NULL && number < i - 1)
{
p = p->next;//只是寻找到第i-1节点
number++;
}
if (p == NULL)
printf("插入位置不合法");
printf("插入位置为%d是%d\n", i, e);
LNode*s = (LNode*)malloc(sizeof(LNode));//为插入元素分配一个节点
s->data = e;//将e赋值新节点的数据域
s->next = p->next;//将插入元素的指针指向第i+1个元素
p->next = s;//将第i-1和插入元素连接
}
}
void ListDelet(LinkList &L, int i)
{
if (i < 1)
printf("删除位置不合法");
LNode *P;//用来指向查询元素的指针
int number = 0;//记录节点的位置
P = L;//查询节点应从头开始,所以指向头节点
while (P != NULL && number < i - 1)
{
P = P->next;//只是寻找到第i-1节点
number++;
}
if (P== NULL)
printf("删除内容为空");
LNode*Q = P->next;
int e;
e = Q->data;//记录删除的数据
P->next = Q->next;
free(Q);//释放掉该节点
printf("删除元素%d成功\n",e);
}
void GetElem(LinkList L, int i)
{
if (i < 0)
printf("查询位置不合法");
else {
LNode* P;//创建一个记录节点的指针
int number = 0;//记录查询到几个节点
P = L->next;//指向头节点,从头节点开始查询变量
if (i == 0)
printf("头节点为空");//头节点不存放数据
while (P != NULL && number < i)
{
P = P->next;//寻找到第i节点
number++;
}
printf("查询第%d个元素为%d\n", i,P->data );
}
}
void GetElem_data(LinkList L, int e)
{
LNode*P;//分配一个节点
P = L->next;
int number = 1;
while (P!=NULL&&P->data!=e)
{
P = P->next;
number++;
}
if (P = NULL)
{
printf("单链表中没有该元素");
}
else
printf("链表中有该元素位置位%d",number);
}
void main()
{
LinkList L;
InitList(L);//初始化一个带头节点的单链表
CreatList(L);//输入元素
ListInsert(L,3,99);//插入元素(按位)
ListInsert_no(L, 1, 11);//不带头节点
ListDelet(L, 3);//删除节点数据
GetElem(L,3);//按位查找
GetElem_data(L,3);//按值查找
ShowList(L);//打印表
}