链表的增删改查
Note:本文章用到有C++的引用,前面的顺序表的增删查也是
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
/*1.创建指针结构体*/
typedef int ElemType;
typedef struct LNode {
ElemType data;//数据域
struct LNode* next;//指针域
}LNode,*LinkList;
/*
2.头插法创建新链表{
2.1 产生一个头节点L
2.2 将头节点的指针域变为空
2.3 循环读取新的数据(3,4,5,6,7,9999 读取的数据){
2.3.1 申请一个新空间,给s(结构体类型的)
2.3.2 将读取的新数据赋值给s的数据域
2.3.3 修改s的指针域,让新节点的next指针指向链表的第一个元素(头节点之后的元素)
2.3.4 修改L的指针域
2.3.5 进行下一次的数据的读取
}
返回头节点
}
*/
LinkList CreateList1(LinkList& L)
{
LNode* s; int x;//创建指向接结构体的指针,以及存放数据的变量
L = (LinkList)malloc(sizeof(sizeof(LNode)));//产生一个头节点L
L->next = NULL; //将头节点的指针域变为空
//循环读取新的数据(3,4,5,6,7,9999 读取的数据)
scanf("%d",&x);
while (x!=9999)
{
s = (LNode*)malloc(sizeof(LNode));//申请一个新空间,给s(结构体类型的)
s->data = x;//将读取的新数据赋值给s的数据域
s->next = L->next;//修改s的指针域,让新节点的next指针指向链表的第一个元素(头节点之后的元素)
L->next = s;//修改L的指针域
scanf("%d",&x);
}
return L;
}
/*
3.打印链表中的每一个节点的值
*/
void PrintList(LinkList L)
{
//为什么这里可以用L,不会改变L的值,因为函数是值传递,并没有用引用
L = L->next;
while (L!=NULL)
{
printf("%3d",L->data);//打印当前节点数据
L = L->next;//指向下一个节点
}
}
/*
4.尾插法创建链表
LinkList CreateList2(LinkList &L){
//4.0 创建变量x用于数据的读取
//4.1 申请带头结点的链表
//4.2 创建LNode *s,*r=L;进行插入操作,其中r代表的是链表的表尾的节点,指向链表的尾部
//4.3 循环读取数据(3 4 5 6 7 9999){
//4.3.1 新申请一个新节点,让s指向
//4.3.2 s(新节点)的数据域 = 读取的数据x
//4.3.3 r(尾节点)的指针域指向s(新节点)
//4.3.4 r(尾节点)指向s(本质:就是让r尾节点始终指向最后一个节点)
//4.3.5 进行下一次的数据的读取
}
//4.4 循环结束后,将尾节点的指针域变为NULL;
//4.5 返回链表的头指针
}
*/
LinkList CreateList2(LinkList &L) {
int x; //创建变量x用于数据的读取
L = (LinkList)malloc(sizeof(LNode)); //申请带头结点的链表
LNode *s, *r = L; //创建LNode *s,*r=L;进行插入操作,其中r代表的是链表的表尾的节点,指向链表的尾部
//L->next = NULL;
scanf("%d",&x);
while (x!=9999)
{
s = (LNode*)malloc(sizeof(LNode)); //新申请一个新节点 ,让s指向
//s->next = r->next;
s->data = x; //s(新节点)的数据域 = 读取的数据x
r->next = s; //r(尾节点)的指针域指向s(新节点)
r = s; //r(尾节点)指向s(本质:就是让r尾节点始终指向最后一个节点)
scanf("%d",&x); //进行下一次的数据的读取
}
r->next = NULL; //循环结束后,将尾节点的指针域变为NULL;
return L;
}
/*
5.按序号查找节点值
LNode* GetElem(Linklist L,int i){
}
*/
LNode* GetElem(LinkList L,int i) {
int j = 0;//用于标记第几个,初始值为0,表示没有标记
while (L != NULL && j != i)
{
L = L->next;
j++;
}
return L;
}
/*
6.按值查找
LNode* LocateElem(LinkList L, ElemType e){
6.1 然后while循环,结束条件是L指向最后一个节点的指针域或者L的指针域为e
即L != null && L->data != e{
6.2.1 继续遍历下一个节点
}
}
*/
LNode* LocateElem(LinkList L, ElemType e) {
while (L != NULL && L->data != e)
{
L = L->next;
}
return L;
}
/*
7.新节点插入第i个位置
bool ListFrontInsert(LinkList &L,int i,ElemType e){
7.1 定义一个变量j并初始化为1,用于统计第几个节点
7.2 定义一个结构体指针变量f并且初始化指向第一个节点,用于遍历查找
7.3 创建一个结构体指针变量s,用于指向新节点
7.4 循环遍历{
7.4.1 让f指向下一个节点
}
7.5 循环结束,判断是否找到了前驱节点,
若是{
7.6 找到了要插入的节点的前驱节点,然后让s的指针域指向f的指针域
7.7 f的指针域指向s
返回true
}若不是{
返回false
}
}
*/
bool ListFrontInsert(LinkList &L, int i, ElemType e) {
int j = 1;
LNode *f = L;
LNode *s = (LNode*)malloc(sizeof(LNode));
s->data = e;
while (f != NULL && j <= i-1)
{
f = f->next;
j++;
}
if (f)
{
s->next = f->next;
f->next = s;
return true;
}
else
{
return false;
}
}
/*
8.删除第i个节点
bool ListFrontInsert(LinkList &L, int i){
8.1 定义一个变量j
8.2 定义一个结构体指针变量f并且初始化指向第一个节点,用于遍历查找
8.3 创建一个结构体指针变量s,指向一个删除节点
8.4 循环遍历
}
*/
bool ListDelete(LinkList &L, int i) {
int j = 1;
LNode* f = L;
LNode * s = NULL;
while (f != NULL && j <= i-1)
{
f = f->next;
j++;
}
if (f)
{
s = f->next;
f->next = f->next->next;
free(s);
return true;
}
else
{
return false;
}
}
int main()
{
LinkList L;//定义链表头,是结构体指针类型
//头插法创建链表
//CreateList1(L);//输入的数据是3 4 5 6 7 9999
//尾插法创建链表
CreateList2(L);//输入的数据是3 4 5 6 7 9999
//链表打印
PrintList(L);
printf("\n*****************\n");
//按序号查找节点的值
int i; LNode *rs;
scanf("%d",&i);
rs = GetElem(L,i);
if (rs)
{
printf("查找成功,值为:%d\n",rs->data);
}
else
{
printf("查找失败\n");
}
printf("*****************\n");
//按值查找
ElemType e = 5;
rs = LocateElem(L, e);
if (rs)
{
printf("按值查找成功! 值为:%d\n",rs->data);
}
else
{
printf("查找失败!\n");
}
printf("*****************\n");
//插入第1个节点
bool res;
res = ListFrontInsert(L, 1, 35);
if (res)
{
printf("插入成功\n");
PrintList(L);
}
else
{
printf("插入失败\n");
}
printf("\n*****************\n");
//删除第1个节点
res = ListDelete(L, 5);
if (res)
{
printf("删除成功\n");
PrintList(L);
}
else
{
printf("删除失败\n");
}
return 0;
}