首页 > 其他分享 >单向链表

单向链表

时间:2023-08-14 18:32:18浏览次数:38  
标签:int LL 单向 next 链表 post data

1. 概念

链表就是将 结点 用链串起来的线性表,链就是 结点 中的指针域。

2. 接口实现

对比操作顺序表的结构体定义

用来操作顺序表的结构体定义

struct SeqList

{

   int data[10];  // 顺序表

   int last;

}


用来操作有头单向链表的结构体定义

struct LinkListNode

{

   int data;

   struct LinkListNode *next;

};

链表 操作链表的结构体就是链表中结点的结构体。

顺序表 操作顺序表的结构体中就包含了顺序表数组。

2.1. 定义操作单向链表的结构体

LL.h

// 1. 定义用来操作有头单向链表的结构体

typedef struct LinkListNode

{

   int data;

   struct LinkListNode *next;

} LLN, *LL;

2.2. 创建空的有头单向链表

在对有头单链表进行操作之前,需要对其进行初始化,即创建一个空的有头单链表。

初始化只需malloc开辟一个结点大小的空间存放有头单向链表头结点,然后让有头单链表中的头结点指针域指向NULL即可。

想要找到单向链表并对其进行操作就需要一个指针来指向单向链表的头结点,该指针就是头指针H

LL.h

#ifndef _LL_H_

#define _LL_H_


#include <stdio.h>

#include <stdlib.h>


// 1. 定义用来操作有头单向链表的结构体

typedef int DataType;


typedef struct LinkListNode

{

   DataType data;

   struct LinkListNode *next;

} LLN, *LL;


// 2. 创建空的有头单向链表

LL LLCreate();


#endif

LL.c

#include "LL.h"


// 2. 创建空的有头单向链表

LL LLCreate()

{

   LL H = (LL)malloc(sizeof(LLN));

   if (NULL == H)

   {

       printf("LLCreate failed, H malloc err.\n");

       return NULL;

   }


   H->next = NULL;


   return H;

}

Test.c

#include "LL.h"


int main(int argc, char const *argv[])

{

   LL H = LLCreate();

   

   return 0;

}

开辟空间存放头结点,并返回指向头结点的指针,该指针称为该链表的头指针。

2.3. 长度

使用伪头指针遍历单向链表

有头单向链表的遍历条件:H->next != NULL

无头单向链表的遍历条件:H != NULL

长度

// 3. 长度

int LLLength(LL H)

{

   int len = 0;


   while (H->next != NULL) // 伪头指针指针域next不为空

   {

       len++;

       H = H->next; // 伪头指针后移

   }


   return len;

}

2.4. 插入

假设要在有头单向链表的post位置插入一个新的结点。

post类比下标,即从0开始。

容错判断 [0, len]

  1. post不能小于0
  2. post不能大于链表的长度

移动伪头指针,使其指向插入位置的前一个结点

for (int i = 0; i < post; i++)

H = H->next;

生成新结点

LL PNew = malloc()

PNew->data = data;

PNew->next = NULL;

插入(先后再前)

PNew->next = H->next;

H->next = PNew;

LL.c

// 4. 有头单向链表指定位置插入数据

void LLInsert(LL H, int post, DataType data)

{

   // 4.1 容错判断  [0, len]

   if (post < 0 || post > LLLength(H))

   {

       printf("LLInsert failed, post not at [0, len].\n");

       return ;

   }


   // 4.2 移动伪头指针,使其指向插入位置前驱post-1

   for (int i = 0; i < post; i++)

       H = H->next;


   // 4.3 开辟新结点存放插入数据

   LL PNew = (LL)malloc(sizeof(LLN));

   if (NULL == PNew)

   {

       printf("LLInsert failed, PNew malloc err.\n");

       return ;

   }

   PNew->data = data;

   PNew->next = NULL;


   // 4.4 插入(先后再前)

   PNew->next = H->next;

   H->next = PNew;

}

Test.c

#include "LL.h"


int main(int argc, char const *argv[])

{

   LL H = LLCreate();


   LLInsert(H, 0, 100);

   LLInsert(H, 1, 111);

   LLInsert(H, 2, 222);

   LLInsert(H, 3, 333);


   int len = LLLength(H);

   printf("LLLength is %d\n", len);


   return 0;

}

2.5. 打印

LL.c

// 5. 打印

void LLPrint(LL H)

{

   while (H->next != NULL) // 伪头指针指针域next不为空

   {

       H = H->next; // 伪头指针后移

       printf("%d\t", H->data);

   }

   printf("\n");

}

Test.c

#include "LL.h"


int main(int argc, char const *argv[])

{

   LL H = LLCreate();


   LLInsert(H, 0, 100);

   LLInsert(H, 1, 111);

   LLInsert(H, 2, 222);

   LLInsert(H, 3, 333);


   int len = LLLength(H);

   printf("LLLength is %d\n", len);


   LLPrint(H);


   return 0;

}

典型HG错误

// 5. 打印

void LLPrint_test(LL H)

{

   for (int i = 0; i < LLLength(H); i++)

   {

       H = H->next;

       printf("第%d次长度为%d\t", i, LLLength(H));

       printf("%d\n", H->data);

   }

}

2.6. 查找

返回指定数据在单向链表中首次出现的位置

思路:

  1. post = 0
  2. 遍历
  1. 如果相等return post
  2. 不等post++
  1. 遍历结束没找到return -1

LL.c

// 6. 查找指定数据在单向链表中首次出现的位置

int LLFind(LL H, DataType data)

{

   int post = 0;


   while (H->next) // while (H->next != NULL)

   {

       H = H->next;

       if (H->data == data)

           return post;

       else

           post++;

   }

   return -1;

}

2.7. 修改

修改指定位置数据

post类比下标,即从0开始。

LL.c

// 7. 修改指定位置数据

void LLModify(LL H, int post, DataType data)

{

   // 7.1 容错判断 [0, len)

   if (post < 0 || post >= LLLength(H))

   {

       printf("LLModify failed, post not at [0, len).\n");

       return;

   }


   // 7.2 移动伪头指针指向post结点

   for (int i = 0; i <= post; i++)

       H = H->next;


   // 7.3 修改数据

   H->data = data;

}

Test.c

#include "LL.h"


int main(int argc, char const *argv[])

{

   LL H = LLCreate();


   LLInsert(H, 0, 100);

   LLInsert(H, 1, 111);

   LLInsert(H, 2, 222);

   LLInsert(H, 3, 333);


   int len = LLLength(H);

   printf("LLLength is %d\n", len);


   LLPrint(H);


   int post = LLFind(H, 222);

   if (post < 0)

       printf("222 not found.\n");

   else

       printf("222's position is %d\n", post);


   LLModify(H, 2, 999);

   LLPrint(H);


   return 0;

}

标签:int,LL,单向,next,链表,post,data
From: https://blog.51cto.com/u_16225641/7079991

相关文章

  • list 容器(链表)
    1.list基本概念链表(list)是一种物理存储单元上的非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的;将数据进行链式存储。  是一个双向循环链表;链表由一系列结点组成;结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点的指针域;优......
  • 一文学会链表双指针技巧
    1.合并两个有序链表21.合并两个有序链表将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例3:输入:l1=[],l2=[0]输出:[0]提示:两......
  • day04 - 链表part02
     24. 两两交换链表中的节点/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*ListNode(intx):val(x),next(nullptr){}*ListNode(intx,ListNode......
  • redis数据结构链表
    redis数据结构链表数据结构链表节点typedefstructlistNode{//前置节点structlistNode*prev;//后置节点structlistNode*next;//节点的值void*value;}listNode;多个listNode可以通过prev和next指针组成双端链表链表typedefstructlist{//表头节点......
  • day03 - 链表part01
    203. 移除链表元素/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*ListNode(intx):val(x),next(nullptr){}*ListNode(intx,ListNode*next):v......
  • 单链表反转
    单链表反转反转单链表是一个很常见的问题迭代法最直观的方法就是遍历链表的同时将其反转packagemainimport."nc_tools"/**typeListNodestruct{*Valint*Next*ListNode*}*//***代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规......
  • 数据结构与算法 --- 组数、链表、栈和队列(一)
    数组、链表、栈和队列是四种基础数据结构,他们是高级、复杂的数据结构和算法的基础。本篇先来讲述数组,链表,及算法的优化策略。数组定义数组:数组是一种线性表数据结构,它用一组连续的内存空间存储一组具有相同类型的数据。定义中有三个关键词:线性表连续的内存空间相同类型数......
  • 数据结构与算法 --- 组数、链表、栈和队列(二)
    继数据结构与算法---组数、链表、栈和队列(一)讲解完数组,链表及算法的优化策略之后,接下来继续讲解两种特殊的线性表结构,栈和队列。栈对“栈”有一个很形象的比喻,栈就像一摞叠在一起的盘子,放盘子时,只能放在上面,不能将盘子插入到中间的任意位置;取盘子时,只能从最上面取,不能从中间任......
  • 链表
    链表的特点是用一组位于任意位置的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以不连续。链表是容易理解和操作的基本数据结构,它的操作有初始化、添加、遍历、插入、删除、查找、释放等。P1996约瑟夫问题-洛谷|计算机科学教育新生态(luogu.com.cn)题意:$n......
  • 链表和数组的区别
    链表和数组的区别链表逻辑上相邻的元素在物理位置上不一定相邻。优点:插入、删除效率高,不需要一个连续的很大的内存缺点:查找某一个位置的元素效率低。数组优点:存取速度快缺点:1.整块连续空间,占很大内存。2.插入或删除数据效率低、不方便链表数组逻辑上相......