#include<stdio.h>
#include<stdlib.h>
#include <stdbool.h>
typedef int ElementType;
//线性表的链式存储
typedef struct LNode *PtrToLNode;
struct LNode{
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;//这里的位置是结点的地址
typedef PtrToLNode List;
//单链表的初始化
List Init()
{
List L=(List )malloc(sizeof(struct LNode));
L->Data =0;//头结点的数据域代表链表的长度
L->Next =NULL;
return L;
}
//单链表的输入 ,带头结点
void read(List L,int n)
{
L->Data +=n;
List tmp,p;
tmp=L;
int i;
for(i=0;i<n;i++){
p=(List)malloc(sizeof(struct LNode));
tmp->Next =p;
p->Next =NULL;
scanf("%d",&p->Data );
tmp=p;
}
}
//1.求表长
/*
将链表从头到尾遍历一遍
*/
int Length(List L)
{
Position p;
int cnt=0;//初始化计数器
p=L;//p指向表的第一个结点
while(p){
p=p->Next ;
cnt++;//当前p指向的是第cnt个结点
}
return cnt;
}
//2.查找
/*
(1)按序号查找
从链表的第一个元素结点起,判断当前结点是否是第K个
若是,则返回该结点的值,否则继续向后。如果没有第K个结点则返回错误信息
*/
#define ERROR -1 //一般定义为表中元素不可能取到的值
ElementType FindKth(List L,int k)
{
//根据指定的位序K,返回l中相应元素
Position p;
int cnt=1;//位序从1开始
p=L;
while(p&&cnt<k){
p=p->Next ;
cnt++;
}
if((cnt==k)&&p)
return p->Data ;//找到第k个
else
return ERROR;//未找到,返回错误信息
}
/*
(2)按值查找,即定位Find
从头到尾遍历,直到找到为止
判断结点值是否为X,找到则返回该结点的位置 ,未找到返回错误信息
*/
#define ERROR 0
int Find(List L,ElementType X)
{
Position p=L;//p指向L的第一个结点
int cnt;
while(p&&p->Data !=X){
p=p->Next ;
cnt++;
}
if(p)
return cnt;
else
return ERROR;
//if-else语句可直接用return p;
}
//3.插入
/*
(1)不带头结点的链表式插入
在指定位序i(1<=i<=n+1)前插入一个新元素X
如果i!=1,则找到位序为i-1的结点pre
若存在,则申请一个新结点并在数据域填上相应的X,然后将新结点插入到结点pre后,返回结果链表
注意:若插入不成功则返回的指针为NULL,不能使用"L=Insert(L,X,i)" ,用一个临时指针接收插入函数的返回值
*/
//#define ERROR NULL
//List Insert(List L,ElementType X,Position i)
//{
// Position tmp,pre;
// tmp=(Position)malloc(sizeof(struct LNode));
// tmp->Data =X;
// if(i==1){
// //新结点插入表头
// tmp->Next =L;
// return tmp;//返回新表头指针
// }
// else{
// //查找位序为i-1的结点
// int cnt =1;//位序从1开始
// pre=L;
// while(pre&&cnt<i-1) {
// pre=pre->Next ;
// cnt++;
// }
// if(pre==NULL||cnt!=i-1){
// //所找结点不在L中
// printf("插入位置错误!\n");
// free(tmp);
// return ERROR;
// }else {
// //找到了待插入结点的前一个结点pre
// //插入新结点,并且返回表头L
// tmp->Next =pre->Next ;
// pre->Next =tmp;
// return L;
// }
// }
//}
//带头结点的链式表的插入函数
/*
(2)不带头结点的链表式插入
为链表增加一个空的"头结点",真正的元素连接在这个空结点之后
*/
bool Insert(List L,ElementType X,int i)
{
//这里默认L有头结点
Position tmp,pre;
int cnt=0;
//查找位序为i-1的结点
pre=L;
while(pre&&cnt<i-1){
pre=pre->Next ;
cnt++;
}
if(pre==NULL||cnt!=i-1){
//所找结点不在链表中
printf("插入位置错误!\n");
return ERROR;
}else{
//找到了待插入结点的前一个结点pre
//若i=1,pre就指向表头
tmp=(Position)malloc(sizeof(struct LNode));
tmp->Data =X;
tmp->Next =pre->Next ;
pre->Next =tmp;
return true;
}
}
//4.删除
/*
删除指定位序i的元素
找到被删除结点的前一个元素,然后再删除结点并释放空间
*/
bool Delete(List L,int i)
{
Position tmp,pre;
int cnt =0;
//查找位序为i-1的结点
pre=L;
while(pre&&cnt<i-1){
pre=pre->Next ;
cnt++;
}
if(pre==NULL||cnt!=i-1||pre->Next ==NULL){
//所找结点或位序为i的结点不在L中
printf("删除位置错误!\n");
return false;
}else {
//找到了待删除结点的前一个结点pre
tmp=pre->Next ;
pre->Next=tmp->Next ;
free(tmp);
return true;
}
}
int main()
{
//1.初始化
List L;
L=Init();
int i;
//输入数据
printf("请输入链表结点个数:\n");
int n;
scanf("%d",&n);
printf("请输入%d个数:\n",n);
read(L,n);
//2.查找
//按位序查找
ElementType f=FindKth(L,3);
printf("第2位序上的数为:%d\n",f);//带头结点,1位序上的数是结点数,2开始是输入数据
//按值查找
int p=Find(L,2);
printf("2在链表中的位序为:%d\n",p );
//3.插入
Insert(L,6,2);
printf("在第2位序上插入6后链表为;");
for(i=0;i<n+1;i++){
printf("%d ",L->Next->Data );//1位序上的数是结点数,2开始是输入数据
L=L->Next ;
}
printf("\n");
//4.删除
// Delete(L,2);
// printf("删除第2位序的元素后链表为:\n");
// for(i=0;i<n-1;i++){
// printf("%d ",L->Next->Data );
// L=L->Next ;
// }
// printf("\n");
return 0;
}
运行:
![](https://img-blog.csdnimg.cn/img_convert/03de841096a6c0f211093eb361ea1dcd.png)
![](https://img-blog.csdnimg.cn/img_convert/2cc12b81ad6360cbd2a26e3ffeab2417.png)