果然是写一次就有一次新的发现,防止忘记也忘了刚接触的小伙伴有个头绪特写了这篇单链表的文章。
单链表的概念就不再多说,只实现了相应的基本操作,一切从简,从简单的方式来书写,可能会觉得比较麻烦但思路绝对清晰。
如有错误欢迎指出,相应解释都放在注释里面了。
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
typedef struct LinkList{//定义单链表的结构体
int data;//数据域
struct LinkList *next;//指针域
}LinkList,*LinkListPtr;//LinkList 结构体,LinkListPtr 结构体指针
void LinkList_Init(LinkListPtr L){//链表的初始化
L->next = NULL;//其实并没有什么用在写入数据的时候也可以执行这一步
return;//一切从简,不搞花里胡哨的东西
}
/*void LinkList_Create(LinkListPtr L){//前插法创建链表,顾名思义每次遇到的元素都放在最前面
int x;
printf("输入要存储的数据(0结束输入):\n");
while(1){//死循环 可以一直输入数据
scanf("%d",&x);
if(x){
LinkListPtr p;//这里目的是创建一个结构体,
p = (LinkListPtr )malloc(sizeof(LinkList));//申请相应大小的内存
p->data = x;//数据域存储数据
p->next = L->next;//头插法的写法,看不懂可以画个图,多写几个节点就看懂了
L->next = p;//继续画图
}else break;
}
return;
}*/
void LinkList_Create(LinkListPtr L){//后插法创建链表,每次元素都放在最后一位
int x;
printf("输入要存储的数据(0结束输入):\n");
LinkListPtr t = L;//需要一个临时变量来暂时代替头指针的作用,后续再代替上一个节点的作用
while(1){
scanf("%d",&x);
if(x){
LinkListPtr p = (LinkListPtr)malloc(sizeof(LinkList));
p->data = x;
p->next = NULL;
t->next = p;//画图就完事了
t = p;
}else break;
}
return;
}
void LinkList_Print(LinkListPtr L){//链表的打印
LinkListPtr p = L->next;
while(p != NULL){
printf("%d\t",p->data);
p = p->next;
}
printf("\n");
return;
}
bool LinkList_GetElem(LinkListPtr L,int pos,int *elem){//获取到某个位置的元素
int i = 1;//定义一个计数器
LinkListPtr p = L->next;//指向第一个节点
while(p != NULL && i <= pos){//位置合法且不是最后一个节点
if( i== pos){//遍历到了相应的位置就开始取值
*elem = p->data;
return true; //还回真,返回的值在主函数中会有作用
}
p = p->next;//继续指向下一个节点
i++;//计数器加一
}
return false;//如果一直没有获取到相应的值就返回假
}
bool LinkList_LocateElem(LinkListPtr L,int elem,int *pos){//获取某个元素在哪个位置
LinkListPtr p = L->next;//第一个节点
int i = 1;//计数器
while(p != NULL){
if(p->data == elem){//遍历到了开始取其位置
*pos = i;
return true;
}
p = p->next;//继续指向下一个节点
i++;//计数器加一
}
return false;//如果一直没有获取到相应的值就返回假
}
int LinkList_Length(LinkListPtr L){//求链表的长度
int len = 0;//计数器
LinkListPtr p = L->next;
while(p != NULL){//一直遍历到最后
len++;
p = p->next;
}
return len;
}
bool LinkList_Insert(LinkListPtr L,int pos,int elem){//在指定位置插入指定元素
int len = LinkList_Length(L);//先获取到链表当前的长度
if(pos < 1 || pos > len +1){//判断位置是否合法,插入的位置应该是1<=pos<=len+1,
//len+1也就是链表的最后位置了
return false;
}
LinkListPtr p = L;//代替头指针的作用
int i = 1;
while(1){
if(pos == i){//如果找到了相应的位置就开始插入
LinkListPtr t = (LinkListPtr)malloc(sizeof(LinkList));//申请一个新节点来插入进去
t->data = elem;//保存要插入的数据
t->next = p->next;//新节点的指针域存放下一个节点的地址
p->next = t;//上一个节点存放新节点的地址
return true;
}
p = p->next;//找不到就继续往下遍历
i++;
}
}
bool LinkList_Delete(LinkListPtr L,int pos){//删除指定位置的元素
int len = LinkList_Length(L);
if(pos < 1 || pos > len ){//判断位置是否合法,要删除的位置应该为1<=pos<=len
return false;
}
LinkListPtr p = L;
LinkListPtr t = L->next;
int i = 1;
while(1){
if(pos == i){
p->next = t->next;//这样写就可以直接让p指向t的下一个节点
free(t);//然后再把t释放掉
return true;
}
p = t;
t = t->next;
i++;
}
}
int main(){
system("color 9F");//看着舒服的颜色
LinkList L;
LinkList_Init(&L);
LinkList_Create(&L);
LinkList_Print(&L);
int x;
int pos;
//以下均为测试 并无其他意义
if(LinkList_GetElem(&L,5,&x)) printf("要取的元素为%d\n",x);
else printf("未取到元素请检查pos是否正确!\n");
if(LinkList_LocateElem(&L,5,&pos)) printf("要取的元素的位置是%d\n",pos);
else printf("未查找到该值!\n");
if(LinkList_Insert(&L,6,99)) printf("插入成功!\n");
else printf("插入失败!\n");
LinkList_Print(&L);
if(LinkList_Delete(&L,6)) printf("删除成功!\n");
else printf("删除失败!\n");
LinkList_Print(&L);
}
Ps:相应的基本操作已经写的很清晰了,不像书上写的简短而复杂,先理解才是最好的。如有错误请指出