参考博文:C语言数据结构-创建链表的四种方法
链表结构图一
链表结构图二
链表结构图三
链表结构图四
一.静态链表
例1:
附例1代码:
#include <stdio.h>
typedef struct node {
int data;
struct node* next;
} Node;
int main()
{
//2.链表内容
Node a,b,c;
a.data = 10;
b.data = 20;
c.data = 30;
//3.链表链接
a.next = &b;
b.next = &c;
c.next = NULL; //4.链表结尾
Node * head = &a;//1.链表开头
while(head != NULL)
{
printf("data = %d\n",head->data);
head = head->next;
}
return 0;
}
二.动态链表
静态链表的意义不是很大,主要原因,数据存储在栈上,栈的存储空间有限, 不能动态分配。所以空链表要实现存储的自由,要动态的申请堆里的空间。
例2:
运行:
附例2代码:
#include <stdio.h>
#include <stdlib.h>
//这里创建一个结构体用来表示链表的结点类型
struct node {
int data;
struct node *next;
};
int main()
{
struct node *head,*p,*q,*t;
int i,n,a;
scanf("%d",&n);
head = NULL;//头指针初始为空
for(i=1; i<=n; i++) {
//循环读入n个数
scanf("%d",&a);
//动态申请一个空间,用来存放一个结点,并用临时指针p指向这个结点
p=(struct node *)malloc(sizeof(struct node));
p->data=a;//将数据存储到当前结点的data域中
p->next=NULL;//设置当前结点的后继指针指向空,也就是当前结点的下一个结点为空
if(head==NULL)
head=p;//如果这是第一个创建的结点,则将头指针指向这个结点
else
q->next=p;//如果不是第一个创建的结点,则将上一个结点的后继指针指向当前结点
q=p;//指针q也指向当前结点
}
//输出链表中的所有数
t=head;
while(t!=NULL) {
printf("%d ",t->data);
t=t->next;//继续下一个结点
}
getchar();
getchar();
return 0;
}
2.1尾插法(略)
2.2头插法
例3
运行结果:
附例3代码:
#include <stdio.h>
#include <stdlib.h>
//这里创建一个结构体用来表示链表的结点类型
struct node {
int data;
struct node *next;
};
int main()
{
struct node *head,*p,*q,*t;
int i,n,a;
scanf("%d",&n);
head = NULL;//头指针初始为空
for(i=1; i<=n; i++) {
//循环读入n个数
scanf("%d",&a);
//动态申请一个空间,用来存放一个结点,并用临时指针p指向这个结点
p=(struct node *)malloc(sizeof(struct node));
p->data=a;//将数据存储到当前结点的data域中
p->next=NULL;//设置当前结点的后继指针指向空,也就是当前结点的下一个结点为空
if(head==NULL)
head=p;//如果这是第一个创建的结点,则将头指针指向这个结点
else
q->next=p;//如果不是第一个创建的结点,则将上一个结点的后继指针指向当前结点
q=p;//指针q也指向当前结点
}
scanf("%d",&a);//读入待插入的数
t=head;//从链表头部开始遍历
while(t!=NULL) {
//当没有到达链表尾部的时候循环
if(t->next->data > a) {
//如果当前结点下一个结点的值大于待插入数,将数插入到中间
p=(struct node *)malloc(sizeof(struct node));//动态申请一个空间,
用来存放新增结点
p->data=a;
p->next=t->next;//新增结点的后继指针指向当前结点的后继指针所指向的结点
t->next=p;//当前结点的后继指针指向新增结点
break;//插入完毕退出循环
}
t=t->next;//继续下一个结点
}
//输出链表中的所有数
t=head;
while(t!=NULL) {
printf("%d ",t->data);
t=t->next;//继续下一个结点
}
getchar();
getchar();
return 0;
}
例:创建,打印,插入,删除节点;模块化编程
本例来自:https://www.bilibili.com/video/BV1Rb411F738?t=1904
打印节点:
插入节点:
删除节点:
附上例代码:
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;//数据域
struct Node* next;//指针域
};
//创建一个链表
struct Node* createList()
{
struct Node* headNode=(struct Node*)malloc(sizeof(struct Node));
//headNode成为了结构体变量
//变量使用之前必须被初始化
//headNode->data=1;
headNode->next=NULL;
return headNode;
}
//创建一个节点
struct Node* createNode(int data)
{
struct Node* newNode=(struct Node*)malloc(sizeof(struct Node));
newNode->data=data;
newNode->next=NULL;
return newNode;
}
//打印节点
void printList(struct Node* headNode)
{
struct Node* pMove=headNode->next;
while(pMove)
{
printf("%d\t",pMove->data);
pMove=pMove->next;
}
printf("\n");
}
//插入节点,参数:插入那个链表,插入节点的数据是多少
void insertNodeByhead(struct Node* headNode,int data)
{
//1.创建插入的节点
struct Node* newNode=createNode(data);
newNode->next=headNode->next;
headNode->next=newNode;
}
//删除节点(指定位置删除)
void deleteNodeByAppoin(struct Node* headNode,int posData)
{
struct Node* posNode=headNode->next;
struct Node* posNodeFront=headNode;
if(posNode==NULL)
printf("无法删除链表为空\n");
else
{
while(posNode->data!=posData)
{
posNodeFront=posNode;
posNode=posNodeFront->next;
if(posNode==NULL)
{
printf("没有找到相关信息,无法删除\n");
return;
}
}
posNodeFront->next=posNode->next;
free(posNode);
}
}
int main()
{
struct Node* list=createList();
insertNodeByhead(list,1);
insertNodeByhead(list,2);
insertNodeByhead(list,3);
printList(list);
deleteNodeByAppoin(list,2);
printList(list);
return 0;
}
例:同样来自:https://www.bilibili.com/video/BV1Rb411F738?t=1904
附上例代码:
#include<stdio.h>
#include<stdlib.h>
struct student
{
char name[20];
int num;
int math;
};
struct Node
{
struct student data;//数据域
struct Node* next;//指针域
};
//创建一个链表
struct Node* createList()
{
struct Node* headNode=(struct Node*)malloc(sizeof(struct Node));
//headNode成为了结构体变量
//变量使用之前必须被初始化
//headNode->data=1;
headNode->next=NULL;
return headNode;
}
//创建一个节点
struct Node* createNode(struct student data)
{
struct Node* newNode=(struct Node*)malloc(sizeof(struct Node));
newNode->data=data;
newNode->next=NULL;
return newNode;
}
//打印节点
void printList(struct Node* headNode)
{
struct Node* pMove=headNode->next;
printf("name\tnum\tmath\n");
while(pMove)
{
printf("%s\t%d\t%d\n",pMove->data.name,pMove->data.num,pMove->data.math);
pMove=pMove->next;
}
printf("\n");
}
//插入节点,参数:插入那个链表,插入节点的数据是多少
void insertNodeByhead(struct Node* headNode,struct student data)
{
//1.创建插入的节点
struct Node* newNode=createNode(data);
newNode->next=headNode->next;
headNode->next=newNode;
}
//删除节点(指定位置删除)
void deleteNodeByAppoinNum(struct Node* headNode,int num)
{
struct Node* posNode=headNode->next;
struct Node* posNodeFront=headNode;
if(posNode==NULL)
printf("无法删除链表为空\n");
else
{
while(posNode->data.num!=num)
{
posNodeFront=posNode;
posNode=posNodeFront->next;
if(posNode==NULL)
{
printf("没有找到相关信息,无法删除\n");
return;
}
}
posNodeFront->next=posNode->next;
free(posNode);
}
}
int main()
{
struct Node* list=createList();
struct student info;
while(1)
{
printf("请输入学生的姓名 学号 数学成绩:");
scanf("%s%d%d",info.name,&info.num,&info.math);
insertNodeByhead(list,info);
printf("(continue(Y/N))?");
setbuf(stdin,NULL);
int choice=getchar();
if(choice=='N'||choice=='n')
{
break;
}
}
printList(list);
return 0;
}
3.链表反转
4.链表销毁
附代码:
//链表销毁
void destroyList(Node * head)
{
Node * p = NULL;
while(head) {
//有多少个malloc就有多少个free
p = head->next;
free(head);
head = p;
}
}