链表的创建与插入
链表的创建格式:
//定义结点类型
typedef struct _Node {
int data;
//数据类型,你可以把int型的data换成任意数据类型,包括结构体struct等复合类型
struct _Node *next;
//单链表的指针域
} Node,*LinkedList;
//Node表示结点的类型,LinkedList表示指向Node结点类型的指针类型
链表的本质上是结构体。
链表的初始化格式:
LinkedList listinit(){
Node *L;
L=(Node*)malloc(sizeof(Node)); //开辟空间
if(L==NULL){ //判断是否开辟空间失败,这一步很有必要
printf("申请空间失败");
//exit(0); //开辟空间失败可以考虑直接结束程序
}
L->next=NULL; //指针指向空
}
头插入法创建单链表:每次插入结点在头节点之前。
L表示头结点,
p代表新创建的结点,p->next表示p的指针域,p->data表示p的数据域。
//头插法建立单链表
LinkedList LinkedListCreatH() {
Node *L;
L = (Node *)malloc(sizeof(Node)); //申请头结点空间
L->next = NULL; //初始化一个空链表
int x; //x为链表数据域中的数据
while(scanf("%d",&x) != EOF) { // 保证新结点的数据域不为空
Node *p;
p = (Node *)malloc(sizeof(Node)); //申请新的结点
p->data = x; //结点数据域赋值
p->next = L->next; //将结点插入到表头L-->|2|-->|1|-->NULL
L->next = p;
}
return L;
}
尾插入法创建单链表:
//尾插法建立单链表
LinkedList LinkedListCreatT() {
Node *L;
L = (Node *)malloc(sizeof(Node)); //申请头结点空间
L->next = NULL; //初始化一个空链表
Node *r;
r = L; //r始终指向终端结点,开始时指向头结点
int x; //x为链表数据域中的数据
while(scanf("%d",&x) != EOF) {
Node *p;
p = (Node *)malloc(sizeof(Node)); //申请新的结点
p->data = x; //结点数据域赋值
r->next = p; //r和L共用一个指针域,这里相当于L->next = p
//将结点插入到表头L-->|1|-->|2|-->NULL
r = p;
}
r->next = NULL;
return L;
}
链表的打印与修改
遍历输出单链表。
对于p = p->next,意思就是结点p改为它指针域指向的下一个结点。
//便利输出单链表
void printList(LinkedList L){
Node *p=L->next;
int i=0;
while(p){
printf("第%d个元素的值为:%d\n",++i,p->data);
p=p->next;
}
}
链表的元素修改
//链表内容的修改,在链表中修改值为x的元素变为为k。
LinkedList LinkedListReplace(LinkedList L,int x,int k) {
Node *p=L->next;
int i=0;
while(p){
if(p->data==x){
p->data=k;
}
p=p->next;
}
return L;
}
链表的中间插入与删除操作:
free(p)表示删除p结点:
//单链表的删除,在链表中删除值为x的元素
//详情见https://zhuanlan.zhihu.com/p/249144171
LinkedList LinkedListDelete(LinkedList L,int x) {
Node *p,*pre; //pre为前驱结点,p为查找的结点。
p = L->next;
while(p->data != x) { //查找值为x的元素
pre = p;
p = p->next;
}
pre->next = p->next; //删除操作,将其前驱next指向其后继。
free(p);
return L;
}
//单链表的插入,在链表的第i个位置插入x的元素
LinkedList LinkedListInsert(LinkedList L,int i,int x) {
Node *pre; //pre为前驱结点
pre = L;
int tempi = 0;
for (tempi = 1; tempi < i; tempi++) {
pre = pre->next; //查找第i个位置的前驱结点
}
Node *p; //插入的结点为p
p = (Node *)malloc(sizeof(Node));
p->data = x;
p->next = pre->next;
pre->next = p;
return L;
}
细节:点(.)是用于结构体变量访问成员,箭头(->)是用于结构体指针访问成员。
例如:
#include <stdio.h>
int main(void) {
struct Smy {
int a;
};
struct Smy test;
struct Smy * pt;
test.a = 1;
pt = &test;
printf("%d\n", test.a);
printf("%d\n", pt->a);
以上是最为基础的单链表的创建、遍历、插入、查找操作。
此外还有进阶的循环链表、双向链表、循环双向链表的相同操作值得学习。