单链表学习(一)

本文详细介绍了单链表的基本概念,包括头节点和数据节点的创建过程。通过C++代码示例,展示了如何使用malloc函数动态分配内存创建头节点,以及两种数据节点的创建方法:一种是在头节点后直接创建,另一种是依次在每个节点后创建。

   关于链表的概念,原理,具备的优点和缺点,以及示意图等这里就不过多介绍了。书本上或者百度上,其他博主上都可以了解学习。我主要分享链表的一些基础算法。

直接进入主题吧。

今天分享的是关于链表头节点和数据节点的创建。

我们创建一个链表,一般来说都会创建一个头节点,头节点里面不放然后数据,只需要在指针里面放入下一个数据节点的内存地址就行了,当我们需要访问数据节点的时候就从头节点开始依次访问后面的每一个数据节点。

下面就开始创建头节点,

创建头节点

#include<iostream>
#include<stdlib.h>     //调用malloc函数实现动态地址的分配
using namespace std;
struct node    //结构体
{
    int a;  //节点用来存放数据
    struct node *next;    //用来存放下一个节点的地址
};                                           
int main()
{
    node *head;  //定义了一个结构体指针始终用来指向头节点
    node *p;  //定义了一个结构体指针P用来分配内存空间实现节点的创建
    p = (node *)malloc(sizeof(struct node));  //用malloc函数实现节点的创建,其中malloc函数前面需要指明数据类型,结构体是一个数据类型,后面是分配多大的内存,我们通过sizeof计算结构体的大小
    p->next = NULL;   //我们还没有创建数据节点,所以头节点的next不能存放下一个节点的地址,所以赋值NULL
    head = p;//将头节点的地址给head,让头指针始终指向头节点
    return(0);
}

上面的代码成功的创建了一个头节点,并且头节点里面的next指针为NULL(空),head成功指向了头节点。如果头节点里面放了下一个数据节点的内存地址,可以通过head->next去得到下一个数据节点的内存地址,从而实现访问下一个数据节点。

 

头节点创建好了之后,我们开始创建数据节点。

关于创建数据节点一般有两种方法。

第一种每次创建一个数据节点的时候都直接在头节点后面创建,这样创建出来的链表它的数据节点是倒过来的。最后的在最前面,最先建的在最后面,大家可以想想这个画面。

每次在头节点后面创建数据节点,我们需要完成的操作有:

1.让新创建的数据节点指向它后面的数据节点(也就是比他先创建的数据节点)

2.让头节点指向新创建的数据节点

这样就实现了有序的链表创建

如下图所示,首先创建了头节点,然后再头节点后面插入数据节点1,然后继续再头节点后面插入数据节点2

我将创建节点写在了函数里面,当然也可以直接放在主函数里面,具体需要看你的代码复杂程度。

void node_creat(node *head,int n)   //第一个参数用来接收指向头节点的head指针来找到头节点的位置,第二个参数用来接收需要创建多少个数据节点
{
    node *p;
    int i;
    for (i = 1; i <= n; i++)
    {
        p = (node *)malloc(sizeof(struct node));
        cin >> p->a;    //创建的数据节点需要赋值
        p->next = head->next;  //将头节点指向的数据节点地址给新节点,让新节点指向头节点指向的节点,如果头节点后面没有数据节点,则将NULL给创建的节点。
        head->next = p;//在将新创建的节点的地址给头节点,使头节点指向它
    }
}

通过上面代码实现了第一种数据节点的创建。

 

第二种数据节点的创建不是每次都在头节点后面创建而是依次创建,如创建了第一个数据节点后,就在第一个数据节点后面继续创建第二个数据节点,这样我们的数据节点就不是倒着的了。

实现上面的创建方法也同样很简单,但是需要多用一个指针来指向每次创建的数据节点,通过这个指针来赋值内存地址。就好像是在头节点后面创建的时候,我们都是用head指针实现创建是一样的。

 

void node_creat(node *head,int n)
{
    node *p;
    node *q;  //q指针用来指向每次创建的新数据节点
    q = head;  //首先让q指针指向头节点
    int i;
    for (i = 1; i <= n; i++)
    {
        p = (node *)malloc(sizeof(struct node));
        cin >> p->a;
        p->next = q->next;   //将q指向的数据节点的值给新创建的数据节点,实际上就是将NULL给了新数据节点的next.因为这样的创建新的数据节点每次都是在最后一个。
        q->next = p;//同样的,让q指向的数据节点指向新创建的数据节点
        q = q->next;//创建好了之后q移到到新创建的数据节点,又开始在它的后面继续创建
    }
}

 

今天分享了关于单链表头节点的创建和数据节点创建的两种形式,后面将继续分享单链表的其他基础算法

 

转载于:https://www.cnblogs.com/hzb1224/p/11346522.html

<think>好的,我现在需要处理用户关于单链表学习资料的查询。首先,我需要回顾用户提供的引用内容,看看哪些部分相关。用户提到了五个引用,其中引用[2]、[3]、[4]、[5]都是关于单链表的。特别是引用[2]和[5]详细讨论了单链表的基本操作,比如增删改查,以及创建链表的方法。引用[4]列出了单链表的各种操作题目,可能适合练习。引用[3]提到了其他类型的链表,但用户主要关注单链表。 接下来,我需要按照用户的指示组织回答结构。用户要求结构清晰,分步骤解决问题,并确保内容真实可靠。首先,我应该定义单链表,说明其结构特点,比如节点包含数据和指针,引用[2]和[5]都提到了这点。然后,基本操作部分需要涵盖创建链表的方法,如头插法和尾插法,引用[5]中的代码示例可以用来说明尾插法,而引用[4]提到的上机题目也涉及这些方法。 核心操作部分需要包括插入、删除、查找和遍历。引用[2]提到增删改查和遍历是必不可少的,引用[5]中的代码展示了如何求链表长度,这也是遍历的部分。在插入和删除节点时,需要处理指针的调整,这部分需要详细说明步骤,可能结合引用[2]和[4]中的内容。 应用场景方面,引用[3]提到单链表适用于频繁插入删除的场景,比如内存管理或多项式运算。同时,用户提供的引用中没有直接提到应用场景,可能需要结合般知识补充。 学习资源推荐部分,用户提到的引用[2]、[4]、[5]可以作为推荐的笔记和练习题,特别是引用[5]中的代码示例和引用[4]中的上机题目。同时,可能需要建议用户参考教材或在线教程,但用户没有提供其他引用,所以应集中在现有引用上。 相关问题部分需要生成单链表相关的问题,比如基本操作、复杂度分析、其他结构的比较等,确保问题覆盖用户可能感兴趣的方面。例如,如何实现头插法,或者单链表数组的对比。 需要注意的是,所有数学表达式和公式必须用正确的LaTeX格式,比如时间复杂度$O(n)$。同时,回答中的引用要正确标注,例如在提到增删操作时引用[2],在创建链表的方法时引用[5]和[4]。 最后,检查是否所有要求都满足:使用中文,结构清晰,引用正确,生成相关问题,以及正确的LaTeX格式。确保没有遗漏用户提供的引用内容,并且信息准确可靠。</think># 单链表数据结构学习指南 ## 单链表的定义结构 单链表是由**节点**构成的链式存储结构,每个节点包含: 1. **数据域**:存储元素值 2. **指针域**:存储后继节点的地址($Node.next$) $$\text{节点结构} = \begin{cases} data & \text{数据域} \\ next & \text{指针域} \end{cases}$$ ## 二、基本操作实现 ### 1. 创建链表 - **头插法**:新节点插入在链表头部 示例代码片段: ```c void CreateList_Head(LinkList &L) { L = new LNode; // 创建头节点 L->next = NULL; while(有新数据需要插入) { LNode *s = new LNode; s->next = L->next; L->next = s; } } ``` - **尾插法**:新节点插入在链表末尾[^5] 时间复杂度:$O(n)$ ### 2. 核心操作 #### (1)插入节点 - **步骤**: 1. 定位插入位置的前驱节点 2. 修改新节点指针域 3. 修改前驱节点指针域 时间复杂度:$O(1)$(已知前驱节点时) #### (2)删除节点 ```c void DeleteNode(LinkList &L, int i) { LNode *p = L; int j = 0; while(p && j < i-1) { // 定位前驱节点 p = p->next; j++; } LNode *q = p->next; p->next = q->next; delete q; } ``` #### (3)查找操作 - **按值查找**:遍历链表直至找到目标元素[^2] - **按位置查找**:通过计数器定位节点 #### (4)遍历操作 ```c void TraverseList(LinkList L) { LNode *p = L->next; while(p != NULL) { // 处理数据 p = p->next; } } ``` ## 三、应用场景 1. 需要频繁进行插入/删除操作的场景 2. 动态内存管理 3. 多项式运算表示[^3] 4. 实现栈、队列等数据结构 ## 四、学习资源推荐 1. 青岛大学王卓老师的单链表操作视频讲解[^1] 2. 单链表核心操作代码实现笔记[^5] 3. 数据结构上机实验题集(含链表合并、元素分解等综合应用)[^4] 4. 链表变体学习指南(双链表/循环链表) §§ 1. 如何实现单链表的反转操作? 2. 头插法和尾插法的时间复杂度对比? 3. 单链表数组在内存分配上的主要区别是什么? 4. 如何处理单链表中的环检测问题? 5. 在有序单链表中插入元素如何保持有序性? 6. 单链表双向链表各有什么优缺点?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值