我们先来实现不带头单链表的基本操作:
头文件test.h:
#include<stdio.h>
#include<stdlib.h>
typedef int SLTDataType;
struct SListNode{
SLTDataType data;
struct SListNode*next;
};
typedef struct SListNode SLTnode;
void InitSlist(SLTnode*head);//初始化
void InsertSlistfront(SLTnode**head,SLTDataType x);//头插
void InsertSlistback(SLTnode**head,SLTDataType x);//尾插
void InsertSlist(SLTnode**head,int pos,SLTDataType x);//任意插入
void DeleteSlistfront(SLTnode**head);//头删
void DeleteSlistback(SLTnode**head);//尾删
void DeleteSlist(SLTnode**head,SLTDataType x);//任意删除
声明函数的源文件:
#include"test.h"
void BuySlistnode(SLTDataType x){
SLTnode*newnode=(SLTnode*)malloc(sizeof(SLTnode));
newnode->data=x;
newnode->next=NULL;
if(newnode==NULL)
exit(-1);
return newnode;
}
void InsertSlistfront(SLTnode**head,SLTDataType x){
SLTnode*newnode=BuySlistnode(x);
newnode->next=*head;
*head=newnode;
}
void InsertSlistback(SLTnode**head,SLTDataType x){
SLTnode*newnode=BuySlistnode(x);
if(*head==NULL)
*head=newnode;
else{
SLTnode*tail=*head;
while(tail->next){
tail=tail->next;
}
tail->next=newnode;
}
}
void DeleteSlistfront(SLTnode**head){
if(*head==NULL){
printf("该链表是空的");
exit(-1);
}
else{
SLTnode*next=(*head)->next;
free(*head);
*head=NULL;
}
}
void DeleteSlistback(SLTnode**head){
if(*head==NULL){
printf("该链表是空的");
exit(-1);
}
else if(*head->next==NULL){
free(*head);
*head=NULL;
}
else{
SLTnode*tail=head->next;
while(tail){
tail=tail->next;
}
free(tail);
tail=NULL;
}
}
void DeleteSlist(SLTnode**head,int pos){
if(pos==*head)
DeleteSlistfront(head);
else{
SLTnode*fir=*head->next;
SLTnode*ne=*head
while(fir->data!=pos){
ne=ne->next;
fir=fir->next;
}
ne->next=fir->next;
free(fir);
fir=NULL;
}
}
[案例一]反转链表
反转链表有两个思路,第一个思路是将每一个结点指向下一个结点的箭头转换成反方向,第二个思路就是头插法的运用。
思路一:
struct SLTnode*reverse(SLTnode*head){
if(head==NULL)
return ;
SLTnode*n1=NULL;
SLTnode*n2=head;
SLTnode*n3=n2->next;
while(n2!=NULL){
n2->next=n1;
n1=n2;
n2=n3;
if(n3)
n3=n3->next;
}
return n1;
}
思路二:
SLTnode*reverse(SLTnode*head){
SLTnode*cur=head;
SLTnode*newnode=NULL;
while(cur){
SLTnode*nex=cur->next;
cur->next=newnode;
newnode=cur;
cur=next;
}
return newnode;
}
[案例二]查找中间结点
思路是把链表分为奇数个元素的链表和偶数个元素的链表,设计两个指针,分别为快指针和慢指针,快指针走两步慢指针走一步,直到快指针是空或指向最后一个元素。
SLTnode*middlenode(SLTnode*head){
SLTnode*slow=head,*fast=head;
while(fast&&fast->next){
slow=slow->next;
fast=fast->next->next;
}
return slow;
}