数据结构:程序加图示分析单链表的插入和删除操作

本文详细分析了单链表结构,包括插入和删除操作。在插入操作中,即使链表为空也能优雅处理。删除操作则需要找到节点的前趋,对于首个节点的删除需要特殊处理。通过示例程序和流程图,阐述了如何消除特殊情况,简化代码逻辑。

下图展示了单链表的基本结构:

head指针是链表的头指针,指向第一个节点,每个节点的next指针域指向下一个节点,最后一个节点的next指针域为NULL,在图中用0表示。

下面先来看程序(栈的链式存储实现,另外一个实现点这里)和对应的输出(注意输出前进行了链表反转(见《单链表反转》,否则程序后面的while循环输出的顺序是250,200,100),接着来分析程序:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

/* linkedlist.h */

#ifndef LINKEDLIST_H
#define LINKEDLIST_H

typedef  struct node *link;
struct node
{
     unsigned  char item;
    link next;
};

link make_node( unsigned  char item);
void free_node(link p);
link search( unsigned  char key);
void insert(link p);
void deletep(link p);
void traverse( void (*visit)(link));
void reverse( void);
void destroy( void);
void push(link p);
link pop( void);

#endif
 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
参考提供的引用内容,未提及数据结构单链表插入步骤的图示。但可以根据代码描述总结插入步骤并进行文字示意。 #### 单链表在第 i 个位置之前插入新元素的步骤 1. **寻找第 i - 1 个结点**:从链表头开始遍历,用指针 `p` 指向当前结点,使用一个计数器 `j` 记录当前位置。当 `p` 不为空且 `j` 小于 `i - 1` 时,`p` 向后移动,`j` 1。若遍历结束后 `j` 不等于 `i - 1`,则表示插入位置不合适。 2. **生成新结点**:使用 `malloc` 函数为新结点 `s` 分配内存空间,若分配失败则返回。 3. **插入结点**:将新结点 `s` 的数据域赋值为要插入的值 `x`。然后将 `s` 的 `next` 指针指向原来第 `i` 个结点(即 `p` 的 `next` 结点),再将 `p` 的 `next` 指针指向 `s`。 以下是文字示意的图示步骤: - **初始状态**: ```plaintext 头结点 -> 结点1 -> 结点2 -> 结点3 -> ... -> 结点i-1 -> 结点i -> ... p ``` - **找到第 i - 1 个结点**: ```plaintext 头结点 -> 结点1 -> 结点2 -> 结点3 -> ... -> 结点i-1 -> 结点i -> ... p ``` - **生成新结点 s 并赋值**: ```plaintext 头结点 -> 结点1 -> 结点2 -> 结点3 -> ... -> 结点i-1 -> 结点i -> ... p 新结点 s (数据域为 x) ``` - **插入结点 s**: ```plaintext 头结点 -> 结点1 -> 结点2 -> 结点3 -> ... -> 结点i-1 -> s -> 结点i -> ... p ^ | +------ s->next = p->next | p->next = s ``` #### 单链表按值插入新元素的步骤 1. **新建结点**:为新结点 `newNode` 分配内存空间,若分配失败则返回。将新结点的值赋值为要插入的值 `new_value`。 2. **处理链表为空的情况**:若当前链表为空(即 `current` 为 `NULL`),则将 `current` 指向新结点 `newNode`,并将 `newNode` 的 `link` 指针置为 `NULL`。 3. **寻找插入位置**:使用两个指针 `previous` `current`,从链表头开始遍历。当 `current` 不为空且 `current` 的值小于 `new_value` 时,`previous` 指向 `current`,`current` 向后移动。 4. **插入结点**:将新结点 `newNode` 的 `link` 指针指向 `current`,将 `previous` 的 `link` 指针指向 `newNode`。 以下是文字示意的图示步骤: - **初始状态**: ```plaintext 头结点 -> 结点1 (值为 a) -> 结点2 (值为 b) -> 结点3 (值为 c) -> ... current ``` - **新建结点 newNode**: ```plaintext 头结点 -> 结点1 (值为 a) -> 结点2 (值为 b) -> 结点3 (值为 c) -> ... current 新结点 newNode (值为 new_value) ``` - **寻找插入位置**:假设 `new_value` 介于 `b` `c` 之间。 ```plaintext 头结点 -> 结点1 (值为 a) -> 结点2 (值为 b) -> 结点3 (值为 c) -> ... previous current 新结点 newNode (值为 new_value) ``` - **插入结点 newNode**: ```plaintext 头结点 -> 结点1 (值为 a) -> 结点2 (值为 b) -> newNode (值为 new_value) -> 结点3 (值为 c) -> ... previous ^ | +------ newNode->link = current | previous->link = newNode ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值