单链表的基本操作
注意,后面的基本都是带有头节点的
不带头结点单向不循序链表:
创建一个单链表
对于每个链表结点,除了存放元素自身的信息外,还需要存放一个指向其后继的指针。
typedef struct Node
{ //定义单链表结点类型
int data; //数据域,可以是别的各种数据类型,本文统一用int类型
struct Node *next; //指针域
}Node;
初始化
通常会用头指针来标识一个单链表,头指针为NULL时表示一个空表。但是,为了操作方便,会在单链表的第一个结点之前附加一个结点,称为头结点。
头结点的数据域可以不设任何信息,也可以记录表长等信息。
头结点的指针域指向线性表的第一个元素结点。如下图所示:
头结点和头指针的区分:
不管带不带头结点,头指针始终指向单链表的第一个结点,而头结点是带头结点的单链表中的第一个结点,结点内通常不存储信息。
注意,以下的都是包含了头节点的
那么单链表的初始化操作就是申请一个头结点,将指针域置空。
/* 申请内存 */
/* 列表初始数据为0 */
/* 列表的下一项指向空 */
Node* InitList()
{
Node* list = (Node*)malloc(sizeof(Node));
list -> data = 0;
list -> next = NULL;
return list;
}
头插法
所谓头插法建立单链表是说将新结点插入到当前链表的表头,即头结点之后。如图所示:
头插法建立的单链表中结点的次序和输入数据的顺序不一致,是相反的。若希望两者的顺序是一致的,则可采用尾插法建立单链表。
可以理解为:
1 2 3 中要用头插法插入一个数字4,那么插入后的排序应该是4 1 2 3
/*
申请内存
插入数据为形参中待插入的数据
更新指向第一项的位置
更新原先列表的下一项指向待插入数据
总数据数++
*/
void headInsert(Node* list, int data)
{
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> next = list -> next;
list -> next = node;
list -> data++;
}
尾插法
所谓尾插法建立单链表是说将新结点插入到当前链表的表尾,即头结点之后。如图所示:
可以理解为:
0 1 2 3 中要用头插法插入一个数字4,那么插入后的排序应该是 0 1 2 3 4
/*
申请内存
插入数据为形参中待插入的数据
待插入的指针的下一项指向NULL
找到列表的最后一项,然后当list -> next为NULL的时候退出while
更新原先列表的下一项 指向 Node
总数据数++
*/
void tailInsert(Node* list, int data)
{
Node* head = list;
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> next = NULL;
list = list -> next;
while(list -> next)
{
list = list -> next;
}
list -> next = node;
head ->data ++;
}
删除操作
将单链表的第 i 个结点删除。
可以理解为:
0 1 2 3 4中要删除一个数字2,那么插入后的排序应该是 0 1 3 4
0 1 2 2 3 4中要删除一个数字2,那么插入后的排序应该是 0 1 2 3 4
/*
先保存当先列表与列表的第一项的位置
然后找到待删除的地点
将列表的下一项 指向 列表下一项的下一项
释放列表的下一项的内存
之后将指针都后移一个
之后列表数据总数相减
*/
void delete(Node* list, int data)
{
Node* preNode = list;
Node* node = list -> next;
while(node)
{
if(node -> data == data)
{
preNode -> next = node->next;
free(node);
list -> data --;
break;
}
preNode = node;
node = node -> next;
}
}
打印
void printfList(Node* list)
{
list = list -> next;
while(list)
{
printf("%d",list -> data);
list = list -> next;
}
printf("\n");
}
总代码
#include <stdio.h>
#include "stdlib.h"
typedef struct Node
{
int data;
struct Node *next;
}Node;
Node* InitList()
{
Node* list = (Node*)malloc(sizeof(Node));
list -> data = 0;
list -> next = NULL;
return list;
}
void headInsert(Node* list, int data)
{
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> next = list -> next;
list -> next = node;
printf("headInsert中list -> next的地址为%p\r\n",list -> next);
list -> data++;
}
void tailInsert(Node* list, int data)
{
Node* head = list;
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> next = NULL;
list = list -> next;
printf("tailInsert中list -> next的地址为%p\r\n",list -> next);
while(list -> next)
{
list = list -> next;
}
list -> next = node;
head ->data ++;
}
void delete(Node* list, int data)
{
Node* preNode = list;
Node* node = list -> next;
while(node)
{
if(node -> data == data)
{
preNode -> next = node->next;
free(node);
node=NU
list -> data --;
break;
}
preNode = node;
node = node -> next;
}
}
void printfList(Node* list)
{
list = list -> next;
while(list)
{
printf("%d",list -> data);
list = list -> next;
}
printf("\n");
}
void main()
{
Node* list = InitList();
headInsert(list,1);
headInsert(list,2);
headInsert(list,3);
headInsert(list,3);
tailInsert(list,4);
tailInsert(list,5);
tailInsert(list,6);
printfList(list);
delete(list,3);
printfList(list);
}