一、单向链表概念
1.既然顺序存储中的数据因为挤在一起而导致需要成片移动,那很容易想到的解决方案是将数据离散地存储在不同内存块中,然后在用来指针将它们串起来。这种朴素的思路所形成的链式线性表,就是所谓的链表。
2.顺序表和链表在内存在的基本样态如下图所示:
二、链表的分类
根据链表中各个节点之间使用指针的个数,以及首尾节点是否相连,可以将链表细分为如下种类:
1.单向链表
2.单向循环链表
3.双向链表
4.双向循环链表
--> 我们这里介绍的就是第一种 <--
三、单向链表功能
1.定义一个结构体
typedef struct node
{
//存放的数据
int data;
//存放下一个节点的指针
struct node *next;
}node; // node == struct node
2.初始化结构体,生成一个新的节点
node *initList(void)
{
//在堆空间开辟内存
node *new = malloc(sizeof(node));
if(new == NULL)
{
printf("malloc fail\n");
return NULL;
}
//开辟的空间数据初始化为0
new->data = 0;
new->next = NULL;
return new;
}
3.头插添加数据
void inset_1(node *head, node *new)
{
new->next = head->next;
head->next = new;
}
4.尾插添加数据
void inset_2(node *head, node *new)
{
node *p=NULL;
for (p = head; p ->next; p=p->next);
p->next=new;
new->next=NULL;
}
5.打印数据
void display(node *head)
{
int i = 0;
node *p = NULL;
for(p = head->next; p != NULL ; p = p->next)
{
printf("%d\t", p->data);
}
printf("\n");
}
6.查找数据
node *find_data(node *head, int data)
{
node *p = NULL;
for(p = head->next; p != NULL ; p = p->next)
{
//判断节点的数据是否等于 查看的数据,如果是,返回节点
if(p->data == data)
{
return p;
}
}
return NULL;
}
7.节点删除
int del_node(node *head, int data)
{
node *del = NULL;
node *p = NULL;
del = find_data(head, data);
if(del == NULL)
{
printf("链表当中没有此数据节点\n");
return -1;
}
//遍历查看del 前缀节点
for(p = head; p != NULL; p = p->next)
{
if(p->next == del)
{
break;
}
}
//将点解下来
p->next = del->next;
del->next = NULL;
free(del);
return 0;
}
8.移动数据头插
int move_node(node *head,int data_1,int data_2)
{
node *p_1 = NULL;
node *p_2 = NULL;
node *q_1 = NULL;
p_1 = find_data(head, data_1);
p_2 = find_data(head, data_2);
if ((p_1 == NULL) || (p_2 == NULL))
{
printf("你输入的数据有不存在的现象\n");
return -1;
}
//遍历查看del 前缀节点
for(q_1 = head; q_1 != NULL; q_1 = q_1->next)
{
if(q_1->next == p_1)
{
break;
}
}
q_1->next=p_1->next;
p_1->next=NULL;
p_1->next=p_2->next;
p_2->next=p_1;
return 0;
}
9.单向链表的销毁
void destroy(node *head)
{
node *p=head->next;
while(p!=NULL)
{
node *pp=p;
p=p->next;
free(pp);
}
head->next=NULL;
printf("已经成功摧毁\n");
}
完整代码
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
//存放的数据
int data;
//存放下一个节点的指针
struct node *next;
}node; // node == struct node
//函数声明
node *initList(void);
void inset_1(node *head, node *new);
void inset_2(node *head, node *new);
void display(node *head);
node *find_data(node *head, int data);
int del_node(node *head, int data);
int move_node(node *head,int data_1,int data_2);
void destroy(node *head);
int main(void)
{
//定义局部变量
char ch;
int data,data1, ret;
node *head, *new, *find;
//生产一个单向链表结构体
head = initList();
while(1)
{
printf("====================请输入你要操作功能====================\n");
printf("\t\t\ta:头插插入\n");
printf("\t\t\tb:尾插插入\n");
printf("\t\t\tc:查找数据\n");
printf("\t\t\td:删除数据\n");
printf("\t\t\te:移动数据\n");
printf("\t\t\tf:摧毁数据\n");
printf("\t\t\tp:显示数据\n");
//等待获取用户输入
ch = getchar();
switch (ch)
{
//头插添加数据
case 'a':
new = initList();
printf("请输入要插入的数据:");
scanf("%d", &new->data);
inset_1(head, new);
break;
//尾插添加数据
case 'b':
new = initList();
printf("请输入要插入的数据:");
scanf("%d", &new->data);
inset_2(head, new);
break;
//查找数据
case 'c':
printf("请输入要查找的数据:");
scanf("%d", &data);
find = find_data(head, data);
if(find == NULL)
{
printf("链表当中没有此数据节点\n");
}
else
{
printf("链表当中有此数据节点\n它的节点地址:%p\n", find);
}
break;
//节点删除
case 'd':
printf("请输入要删除的数据:");
scanf("%d", &data);
ret = del_node(head, data);
if(ret == 0)
{
printf("节点删除完成\n");
}
break;
//移动数据头插
case 'e':
printf("移动到那个数据前面:");
scanf("%d", &data);
printf("请输入要移动的数据:");
scanf("%d", &data1);
ret = move_node(head, data, data1);
if(ret == 0)
{
printf("节点移动完成\n");
}
break;
//单向链表的销毁
case 'f':
destroy(head);
break;
//打印数据
case 'p':
display(head);
break;
default:
printf("输入格式错误,请重新输入!\n");
break;
}
while (getchar() != '\n');
}
return 0;
}
//初始化结构体,生成新的一个节点
node *initList(void)
{
//在堆空间开辟内存
node *new = malloc(sizeof(node));
if(new == NULL)
{
printf("malloc fail\n");
return NULL;
}
//开辟的空间数据初始化为0
new->data = 0;
new->next = NULL;
return new;
}
//头插添加数据
void inset_1(node *head, node *new)
{
new->next = head->next;
head->next = new;
}
//尾插添加数据
void inset_2(node *head, node *new)
{
node *p=NULL;
for (p = head; p ->next; p=p->next);
p->next=new;
new->next=NULL;
}
//打印数据
void display(node *head)
{
int i = 0;
node *p = NULL;
for(p = head->next; p != NULL ; p = p->next)
{
printf("%d\t", p->data);
}
printf("\n");
}
//查找数据,数据存在返回数据所在的节点地址
node *find_data(node *head, int data)
{
node *p = NULL;
for(p = head->next; p != NULL ; p = p->next)
{
//判断节点的数据是否等于 查看的数据,如果是,返回节点
if(p->data == data)
{
return p;
}
}
return NULL;
}
//节点删除
int del_node(node *head, int data)
{
node *del = NULL;
node *p = NULL;
del = find_data(head, data);
if(del == NULL)
{
printf("链表当中没有此数据节点\n");
return -1;
}
//遍历查看del 前缀节点
for(p = head; p != NULL; p = p->next)
{
if(p->next == del)
{
break;
}
}
//将点解下来
p->next = del->next;
del->next = NULL;
free(del);
return 0;
}
//移动数据头插
int move_node(node *head,int data_1,int data_2)
{
node *p_1 = NULL;
node *p_2 = NULL;
node *q_1 = NULL;
p_1 = find_data(head, data_1);
p_2 = find_data(head, data_2);
if ((p_1 == NULL) || (p_2 == NULL))
{
printf("你输入的数据有不存在的现象\n");
return -1;
}
//遍历查看del 前缀节点
for(q_1 = head; q_1 != NULL; q_1 = q_1->next)
{
if(q_1->next == p_1)
{
break;
}
}
q_1->next=p_1->next;
p_1->next=NULL;
p_1->next=p_2->next;
p_2->next=p_1;
return 0;
}
//单向链表的销毁
void destroy(node *head)
{
node *p=head->next;
while(p!=NULL)
{
node *pp=p;
p=p->next;
free(pp);
}
head->next=NULL;
printf("已经成功摧毁\n");
}