一、思维导图
二、实现链表相关操作
1】 按值修改
2】按值查找,返回当前节点的地址 (先不考虑重复,如果有重复,返回第一个)
3】 反转
4】销毁链表
头文件
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
//类型重定义,用于存储数据的类型
typedef int dataType;
//定义一个节点的结构体类型
typedef struct Node
{
union
{
int len; //头节点数据域(链表的节点数)
dataType data; //普通节点数据域(数据)
};
struct Node *Next; //指针域
}linkList, *linkListPtr;
//创建链表
linkListPtr Lklt_create();
//判空
int Lklt_empty(linkListPtr L);
//申请节点 封装数据
linkListPtr Node_create(dataType n);
//头插
int Head_insert(linkListPtr L, dataType n);
//尾插
int Tail_insert(linkListPtr L, dataType n);
//任意位置插入数据
int Will_insert(linkListPtr L, dataType n, int position);
//遍历
void Lklt_show(linkListPtr L);
//头删
int Head_delet(linkListPtr L);
//尾删
int Tail_delet(linkListPtr L);
//任意位置删除数据
int Will_delet(linkListPtr L, int position);
//(按位置)修改数据
int Lklt_Edit(linkListPtr L,dataType n, int position);
//(按值)修改数据
int Lklt_Edit_2(linkListPtr L,dataType m, dataType n);
//(按值)查找数据
linkListPtr Lklt_find(linkListPtr L,dataType n);
//反转
int Reversal(linkListPtr L);
//销毁
void Destory(linkListPtr *L);
#endif
源文件
#include "linkList.h"
//1、创建链表
linkListPtr Lklt_create()
{
//在堆区申请节点大小的空间 头结点
linkListPtr L = (linkListPtr)malloc(sizeof(linkList));
if(NULL == L)
{
//申请失败,返回NULL
printf("创建链表失败!\n");
return NULL;
}
//申请成功,将头结点的数据域置0 指针域指向NULL
L->len = 0;
L->Next = NULL;
printf("创建链表成功!\n");
return L;
}
//2、判空
int Lklt_empty(linkListPtr L)
{
//判断所接收的链表是否合法
if(NULL == L)
{
printf("判空失败!\n");
return 0;
}
return L->len == 0;
//return L->Next == NULL;
}
//3、申请节点 封装数据
linkListPtr Node_create(dataType n)
{
//在堆区申请节点大小的空间
linkListPtr N = (linkListPtr)malloc(sizeof(linkList));
if(NULL == N)
{
//申请失败,返回NULL
printf("创建链表失败!\n");
return NULL;
}
//申请成功,将头结点的数据域赋值 指针域指向NULL
N->data = n;
N->Next = NULL;
return N;
}
//4、头插
int Head_insert(linkListPtr L, dataType n)
{
//判断所接受的链表是否合法
if(NULL == L)
{
printf("头插失败!\n");
return 0;
}
//申请节点 封装数据
linkListPtr N = Node_create(n);
//头插
N->Next = L->Next; //1、插入节点 指向 头节点指向的节点
L->Next = N; //2、头节点 指向 插入节点
//成功插入 链表长度自增
L->len++;
return 1;
}
//5、尾插
int Tail_insert(linkListPtr L, dataType n)
{
//判断链表是否合法
if(NULL == L)
{
printf("尾插失败!\n");
return 0;
}
//申请节点 封装数据
linkListPtr N = Node_create(n);
//尾插
//定义一个遍历的指针
linkListPtr p = L;
for(int i=0; i<L->len; i++)
p = p->Next;
//尾节点 指向 插入节点
p->Next = N;
//成功插入 链表长度自增
L->len++;
return 1;
}
//6、任意插
int Will_insert(linkListPtr L, dataType n, int position)
{
//判断链表是否合法
if(NULL == L)
{
printf("插入失败!\n");
return 0;
}
//判断插入位置是否合法
if(position > L->len+1 || position <= 0)
{
printf("插入失败!\n");
return 0;
}
//申请节点 封装数据
linkListPtr N = Node_create(n);
//任意插
//定义一个遍历的指针
linkListPtr p = L;
for(int i=1; i<position; i++)
p = p->Next;
N->Next = p->Next; //1、插入节点 指向 被插入的节点
p->Next = N; //2、指向 被插入节点 的节点 指向 插入节点
//成功插入 链表长度自增
L->len++;
return 1;
}
//7、遍历
void Lklt_show(linkListPtr L)
{
//判断链表是否合法、非空
if(NULL == L || Lklt_empty(L))
{
printf("遍历失败!\n");
return;
}
//定义一个遍历的指针
linkListPtr p = L;
for(int i=0; i<L->len; i++)
{
p = p->Next;
printf("%d ", p->data);
}
putchar(10);
}
//8、头删
int Head_delet(linkListPtr L)
{
//判断所接受的链表是否合法、非空
if(NULL == L || Lklt_empty(L))
{
printf("头删失败!\n");
return 0;
}
//定义一个指针
linkListPtr q = L->Next; //指向 要删除位置 的节点
//删除(头删)
L->Next = q->Next;
// L->Next = L->Next->Next;
//释放删除位置指针的内存空间、防止野指针
free(q);
q = NULL;
//成功删除 链表长度自减
L->len--;
return 1;
}
//9、尾删
int Tail_delet(linkListPtr L)
{
//判断所接受的链表是否合法、非空
if(NULL == L || Lklt_empty(L))
{
printf("尾删失败!\n");
return 0;
}
//定义一个指针 指向倒数第二个节点
linkListPtr p = L;
for(int i=0; i<L->len-1; i++)
p = p->Next;
//定义一个指针 指向最后一个节点
linkListPtr q = p->Next;
//尾删
p->Next = q->Next;
//释放删除位置指针的内存空间、防止野指针
free(q);
q = NULL;
//成功删除 链表长度自减
L->len--;
return 1;
}
//10、任意删
int Will_delet(linkListPtr L, int position)
{
//判断所接受的链表是否合法、非空
if(NULL == L || Lklt_empty(L))
{
printf("删除失败!\n");
return 0;
}
//判断删除位置是否合法
if(position > L->len || position <= 0)
{
printf("删除失败!\n");
return 0;
}
//任意删
//定义一个指针 指向删除位置的 前一个节点
linkListPtr p = L;
for(int i=0; i<position-1; i++)
p = p->Next;
//定义一个指针 指向删除位置节点
linkListPtr q = p->Next;
//删除
p->Next = q->Next;
//释放删除位置指针的内存空间、防止野指针
free(q);
q = NULL;
//成功插入 链表长度自减
L->len--;
return 1;
}
//11、修改数据(指定位置节点修改)
int Lklt_Edit(linkListPtr L,dataType n, int position)
{
//判断所接受的链表是否合法、非空
if(NULL == L || Lklt_empty(L))
{
printf("修改失败!\n");
return 0;
}
//判断修改位置是否合法
if(position > L->len || position <= 0)
{
printf("修改失败!\n");
return 0;
}
//定义一个指针 指向修改位置 节点
linkListPtr p = L;
for(int i=0; i<position; i++)
p = p->Next;
//判断修改位置的值是否与预修改值一致
if(p->data == n)
{
printf("未发生修改\n");
return 0;
}
//修改
p->data = n;
return 1;
}
//12、修改数据(指定值修改)
int Lklt_Edit_2(linkListPtr L,dataType m, dataType n)
{
//判断所接受的链表是否合法、非空
if(NULL == L || Lklt_empty(L))
{
printf("修改失败!\n");
return 0;
}
//定义一个遍历的指针
linkListPtr p = L;
int flag = 0;
for(int i=0; i<L->len; i++)
{
p = p->Next;
if(p->data == m)
{
flag = 1; //判断是否发生修改
//修改
p->data = n;
}
}
if(flag == 0)
printf("未能修改!\n");
return 1;
}
//13、查找数据(输入值返回地址)
linkListPtr Lklt_find(linkListPtr L,dataType n)
{
//判断所接受的链表是否合法、非空
if(NULL == L || Lklt_empty(L))
{
printf("查找失败!\n");
return NULL;
}
//定义一个遍历的指针
linkListPtr p = L;
for(int i=0; i<L->len; i++)
{
p = p->Next;
//查找
if(p->data == n)
return p;
}
printf("Not found!\n");
return NULL;
}
//14、反转
int Reversal(linkListPtr L)
{
//判断所接受的链表是否合法、非空
if(NULL == L || Lklt_empty(L))
{
printf("反转失败!\n");
return 0;
}
//定义一个遍历的指针
linkListPtr p = L;
for(int i=0; i<L->len; i++)
{
//再定义一个遍历的指针
linkListPtr q = L;
for(int j=0; j<L->len; j++)
{
q = q->Next;
}
//任意插
q->Next = p->Next;
p->Next = q;
p = p->Next;
}
}
//15、销毁
void Destory(linkListPtr *L)
{
//判断所接受的链表是否合法
if(NULL == *L)
{
printf("销毁失败!\n");
return;
}
//释放内存,防止野指针
free(*L);
*L = NULL;
}
测试文件
#include "linkList.h"
int main()
{
//创建链表
linkListPtr L = Lklt_create();
//头插
Head_insert(L, 10);
Head_insert(L, 20);
Head_insert(L, 33);
Head_insert(L, 40);
Head_insert(L, 50);
//尾插
Tail_insert(L, 66);
Tail_insert(L, 55);
Tail_insert(L, 44);
Tail_insert(L, 33);
Tail_insert(L, 22);
//任意插
Will_insert(L, 123, 11);
//遍历
Lklt_show(L);
//头删
Head_delet(L);
//尾删
Tail_delet(L);
//遍历
Lklt_show(L);
//任意删
Will_delet(L, 4);
//遍历
Lklt_show(L);
//(按位置)修改数据
Lklt_Edit(L, 66, 8);
//(按值)修改数据
Lklt_Edit_2(L, 33, 99);
//遍历
Lklt_show(L);
//查找数据
linkListPtr p = Lklt_find(L, 66);
printf("%d\n", p->data);
//头插
Head_insert(L, 10);
//反转
Reversal(L);
//遍历
Lklt_show(L);
//销毁
Destory(&L);
}