小甲鱼 P47 单链表3---单链表插入和删除
单链表和数组相比较,最大的优势是插入元素到指定位置的效率。
(单链表插入)让用户输入若干个整数,按顺序插入单链表之中:
比如将3插入2和4之间。对于单链表,改变指针就可以了。先抹掉2指向4的指针,将2改为指向3,3指向4,两个步骤。
代码如下:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int value;
struct Node *next;
};
void insertNode(struct Node **head, int value)
{
struct Node *previous;
struct Node *current;
struct Node *neww;//新的节点
//头指针
current = *head;
previous = NULL;
//PS:找到符合条件就不进入循环了
while (current != NULL && current->value < value)//循环,迭代查找匹配节点
{
//current=NULL有三种情况:
//1、没找到,传进来是空的单链表
//2、没找到,找到最后都没有找到合适的位置,指向末尾位置
//3、找到了
previous = current;//previous记录current的上一个地址
current = current->next;//current记录current的下一个节点
}
//申请内存空间来存放新的节点
neww = (struct Node *)malloc(sizeof(struct Node));
if (neww == NULL)
{
printf("内存分配失败!\n");
exit(1);
}
neww->value = value;
neww->next = current;
//下面有两种特殊的情况
//1、空的单链表
//2、通常情况,在夹在中间
if (previous == NULL)
{
//当while不被执行时,空的单链表
*head = neww;//直接插入到第一个节点位置
}
else
{
//通常情况,在夹在中间
previous->next = neww;
}
}
void printNode(struct Node *head)
{
struct Node *current;
current = head;
while (current != NULL)
{
printf("%d ", current->value);
current = current->next;
}
putchar('\n');
}
int main(void)
{
struct Node *head = NULL;
int input;
while (1)
{
printf("请输入一个整数(输入-1表示结束):");
scanf("%d", &input);
if (input == -1)
{
break;
}
insertNode(&head, input);
printNode(head);
}
}
单链表删除
比如将刚插入的3删除。对于单链表,改变指针就可以了。先抹掉指向3的指针,再抹掉指向4的指针,将2改为指向4。
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int value;
struct Node *next;
};
void insertNode(struct Node **head, int value)
{
struct Node *previous;
struct Node *current;
struct Node *neww;//新的节点
//头指针
current = *head;
previous = NULL;
//PS:找到符合条件就不进入循环了
while (current != NULL && current->value < value)//循环,迭代查找匹配节点
{
//current=NULL有三种情况:
//1、没找到,传进来是空的单链表
//2、没找到,找到最后都没有找到合适的位置,指向末尾位置
//3、找到了
previous = current;//previous记录current的上一个地址
current = current->next;//current记录current的下一个节点
}
//申请内存空间来存放新的节点
neww = (struct Node *)malloc(sizeof(struct Node));
if (neww == NULL)
{
printf("内存分配失败!\n");
exit(1);
}
neww->value = value;
neww->next = current;
//下面有两种特殊的情况
//1、空的单链表
//2、通常情况,在夹在中间
if (previous == NULL)
{
//当while不被执行时,空的单链表
*head = neww;//直接插入到第一个节点位置
}
else
{
//通常情况,在夹在中间
previous->next = neww;
}
}
void printNode(struct Node *head)
{
struct Node *current;
current = head;
while (current != NULL)
{
printf("%d ", current->value);
current = current->next;
}
putchar('\n');
}
void deleteNode(struct Node **head, int value)
{
struct Node *previous;
struct Node *current;
//头指针
current = *head;
previous = NULL;
//PS:找到符合条件就不进入循环了
while (current != NULL && current->value != value)//循环,迭代查找匹配节点
{
previous = current;//previous记录current的上一个地址
current = current->next;//current记录current的下一个节点
}
//下面有两种特殊的情况 :找不到 和 找到
if (current == NULL)//找不到
{
//找不到也有两种情况:
//1、空链表,没有节点
//2、单链表节点所有遍历过后,节点value与参数value没有匹配的
//此时current指向单链表的末尾
printf("找不到匹配的节点!\n");
return;//使整个函数结束
}
else//找到了
{
//找到了也有两种情况
//1、待删除的节点 在 第一个节点的位置
if (previous == NULL)
{
*head = current->next;
}
else//2、通常情况,在夹在中间
{
previous->next = current->next;
}
free(current);
}
}
int main(void)
{
struct Node *head = NULL;
int input;
printf("开始测试插入整数..\n");
while (1)
{
printf("请输入一个整数(输入-1表示结束):");
scanf("%d", &input);
if (input == -1)
{
break;
}
insertNode(&head, input);
printNode(head);
}
printf("开始测试删除整数..\n");
while (1)
{
printf("请输入一个整数(输入-1表示结束):");
scanf("%d", &input);
if (input == -1)
{
break;
}
deleteNode(&head, input);
printNode(head);
}
}