线性表的链表实现基本操作详解
- 求链表表长
- 查找元素
- 插入元素
- 删除元素
- 初始化含头指针和不含头指针的链表
- 遍历含头指针和不含头指针的链表
注:含头指针(即头指针也携带有效数字)的链表的操作
1. 求链表表长
(1)含头指针
int Length_headvalue( List Ptrl)
{
List p ;
p= Ptrl;//P是一个临时的指针,指向链表的头
int j=0;//计数器
while (p!=NULL)//while(p)
{
p=p->next;
j++;//当前p指向第j个元素
}
return j;
}
(2)不含头指针
int Length( List Ptrl)
{
List p ;
p= Ptrl;//P是一个临时的指针,指向链表的头
int j=-1;//计数器
while (p!=NULL)//while(p)
{
p=p->next;
j++;//当前p指向第j个元素
}
return j;
}
2.查找
①按序号查找
(1)含头指针
(2)不含头指针
②按值查找
(1)含头指针
(2)不含头指针
List FindKth_headvalue(int K,List Ptrl)
{
List p = Ptrl;
int i = 1;
while(p!=NULL && i<K)
{
p=p->next;
i++;
}
if(i==K)
return p;//找到第K项
else //链表中没有第K项
return NULL;
}
(2)不含头指针
List FindKth(int K,List Ptrl)
{
List p = Ptrl;
int i = 1;
while(p!=NULL && i<K+1)
{
p=p->next;
i++;
}
if(i==K+1)
return p;//找到第K项
else //链表中没有第K项
return NULL;
}
②按值查找
(1)含头指针
List FindValue_headvalue(int X,List Ptrl)
{
List p=Ptrl;
while(p!=NULL &&p->Data!=X)
{
p=p->next;//指针往后挪的基本操作
}
return p;//此时也有两种情况,但无论找到的或没找都返回NULL
/* if(p->Data==X)
return p;
else
return NULL;*///若是没找到,此时p==NULL;所以都可以等效返回NULL;
}
(2)不含头指针
List FindValue(int X,List Ptrl)
{
List p=Ptrl->next;
while(p!=NULL &&p->Data!=X)
{
p=p->next;//指针往后挪的基本操作
}
return p;//此时也有两种情况,但无论找到的或没找都返回NULL
/* if(p->Data==X)
return p;
else
return NULL;*///若是没找到,此时p==NULL;所以都可以等效返回NULL;
}
3.插入
在第i-1个结点后插入一个值为X的新节点
插入时关键在于插入的前一个结点是什么!这样才能把新节点接上去
步骤(1)先malloc一块空间,用S指向
步骤(2)再找到链表的第i-1个结点,用P指向
所以如果X插在表头,则需单独考虑。
(1)含头结点
List Insert_headvalue(ElementType X,int i,List Ptrl)
{
List p,s;//p是用于指向原来链表第i-1个元素,s是用来装新结点
if(i==1)//此时没有第i-1个元素,所以用不到p
{
s=(List)malloc(sizeof(struct LNode));
s->Data=X;//显然头指针是含了数值的
s->next=Ptrl;
return s;//注意这里返回的是新链表表头
}
p=FindKth_headvalue(i-1,Ptrl);//只有待插位置之前有结点,才能用此函数找,,因为没有第0位置
if(p==NULL)
printf("参数错误");
else
{
s=(List)malloc(sizeof(struct LNode));
s->Data=X;
s->next=p->next;
p->next=s;//关键语句,千万不能调换顺序
return Ptrl;
}
}
(2)不含头节点
List Insert(ElementType X,int i,List Ptrl)
{
List p,s;//p是用于指向原来链表第i-1个元素,s是用来装新结点
if(i==1)//此时没有第i-1个元素,所以用不到p
{
s=(List)malloc(sizeof(struct LNode));
s->Data=X;
s->next=Ptrl->next;
Ptrl->next=s;
return Ptrl;//注意这里返回的是原链表表头
}
p=FindKth(i-1,Ptrl);//只有待插位置之前有结点,才能用此函数找,,因为没有第0位置
if(p==NULL)
printf("参数错误");
else
{
s=(List)malloc(sizeof(struct LNode));
s->Data=X;
s->next=p->next;
p->next=s;//关键语句,千万不能调换顺序
return Ptrl;
}
}
4.删除
(1)含头节点
List delete_headvalue (int i,List Ptrl)//删除第i个位置上的结点,同样要找到第i-1个结点
{
List p,s;
if(i==1)
{
s=Ptrl;
if(Ptrl!=NULL)
Ptrl=Ptrl->next;
else //此链表为空,无法删除结点,也没有结点需要free
free(s);//一定要记得free,否则会内存泄漏
return Ptrl;
}
/*if(i==1)
{
return Ptrl->next;
}*/
//上面这样写存在两种隐患,一是链表有可能是空的,所以Ptrl->next可能出问题,
//二是没有free可能内存泄漏
else
{
p=FindKth_headvalue(i-1, Ptrl);//此时要找的是待删除结点的前一个结点
if (p==NULL)//这个结点有可能找不到
{
printf("参数错误");
return NULL;
}
else if(p->next==NULL)//此时有可能待删除结点的位置是NULL,也无效
{
printf("第%d个结点不存在",i);
return NULL;//函数在每种情况下都要对应有返回值!
}
else
{
s=p->next;
p->next=s->next;
free(s);//这三句关键语句顺序也不能调换!!!
return Ptrl;
}
/*
else
{不能这样写!这样会无法free待删除结点
p->next=p->next->next;
}*/
}
}
(2)不含头节点
List delete(int i,List Ptrl)//删除第i个位置上的结点,同样要找到第i-1个结点
{
List p,s;
if(i==1)
{
s=Ptrl->next;
if(s!=NULL)
Ptrl->next=s->next;
else //此链表为空,无法删除结点,也没有结点需要free
free(s);//一定要记得free,否则会内存泄漏
return Ptrl;
}
/*if(i==1)
{
return Ptrl->next;
}*/
//上面这样写存在两种隐患,一是链表有可能是空的,所以Ptrl->next可能出问题,
//二是没有free可能内存泄漏
else
{
p=FindKth(i-1, Ptrl);//此时要找的是待删除结点的前一个结点
if (p==NULL)//这个结点有可能找不到
{
printf("参数错误");
return NULL;
}
else if(p->next==NULL)//此时有可能待删除结点的位置是NULL,也无效
{
printf("第%d个结点不存在",i);
return NULL;//函数在每种情况下都要对应有返回值!
}
else
{
s=p->next;
p->next=s->next;
free(s);//这三句关键语句顺序也不能调换!!!
return Ptrl;
}
/*
else
{不能这样写!这样会无法free待删除结点
p->next=p->next->next;
}*/
}
}
5.初始化链表
给出链表的结点个数,建立链表
(1)含头指针
List gen_headvalue( int n)//创建有n个结点的链表
{
List head ,node,end;
int num;
head=(List)malloc(sizeof(struct LNode));
end=head;
int i;
for(i=0;i<n;i++)
{
scanf("%d",&num);
if(i==0)
{
head->Data=num;
}
else
{
node=(List)malloc(sizeof(struct LNode));
node->Data=num;
end->next=node;
end=node;
}
}
end->next=NULL;
return head;
}
(2)不含头指针
List gen( int n)//创建有n个结点的链表
{
List head ,node,end;
int num;
head=(List)malloc(sizeof(struct LNode));
end=head;
int i;
for(i=0;i<n;i++)
{
scanf("%d",&num);
node=(List)malloc(sizeof(struct LNode));
node->Data=num;
end->next=node;
end=node;
}
end->next=NULL;
return head;
}
6.遍历链表
(1)含头指针
void display_headvalue(List Ptrl)
{
while(Ptrl!=NULL)
{
if(Ptrl->next==NULL)
{
printf("%d",Ptrl->Data);
Ptrl= Ptrl->next;
}
else
{
printf("%d ",Ptrl->Data);
Ptrl= Ptrl->next;
}
}
}
(2)不含头指针
void display(List Ptrl)
{
while(Ptrl->next!=NULL)
{
if(Ptrl->next->next==NULL)
{
Ptrl= Ptrl->next;
printf("%d",Ptrl->Data);
}
else
{
Ptrl= Ptrl->next;
printf("%d ",Ptrl->Data);
}
}
}
这里再推荐另一篇相关博文~
线性表的数组实现基本操作 代码+注释详解