首先定义链表数据类型:
typedef int data_t;
typedef struct node{
data_t data;
struct node *next;
}link_t;
打印函数
/*
* 函数名称:show
* 函数功能:打印当前列表数据
* 返回值:若无数据返回-1,有数据返回0
*/
int show(link_t *L){
if(NULL==L->next){ //健壮性判断
puts("none data!");
return -1;
}
link_t *temp=L->next;
while(NULL!=temp){
printf("%d ",temp->data);
temp=temp->next;
}
puts("");
return 0;
}
创建链表函数
/*
* 函数名称:create
* 功能:创建列表
* 返回值:创建失败返回NULL,创建成功返回malloc开辟的首地址。
*/
void *create(void){
link_t *L=(link_t *)malloc(sizeof(link_t));
if(NULL==L){
puts("创建失败!");
return NULL;
}
L->data=-1;
L->next=NULL;
return L;
}
头部插入函数
/*
* 函数名称:headin
* 函数功能:输入数据从头部插入
* 返回值:0
*/
int headin(link_t *L,data_t value){
link_t *temp=create();
temp->data=value;
temp->next=L->next;
L->next=temp;
return 0;
}
创建链表,主函数代码如下:
#include "link.c"
int main(int argc, const char *argv[])
{
link_t *L=create();
if(NULL==L){
return -1;//创建失败退出主函数
}
return 0;
}
头部插入
主函数
while(1){ //循环输入
data_t i;
scanf("%d",&i);
if(-1==i){
break; //输入-1时退出输出
}
headin(L,i);
}
show(L);
头部插入时,最先插入的数据在链表的后面,所以打印时的顺序时相反的。
尾部插入
尾部插入函数
/*
* 函数名称:tailin
* 函数功能:输入数据从尾部插入
* 返回值:0
*/
int tailin(link_t *L,int value){
link_t *temp=L;
while(NULL!=temp->next){ //先将指针指向最后一个数据
temp=temp->next;
}
link_t *temp_2=create();
temp_2->data=value;
temp_2->next=NULL;
temp->next=temp_2;
return 0;
}
尾部插入只需要将主函数中的headin改为tailin,尾部插入,先插入的数据在前,所以打印时时顺序打印。
任意位置插入数据
/*
* 函数名称:anyin
* 函数功能:任意位置插入数据
* 返回值:成功返回0,失败返回-1
*/
int anyin(link_t *L){
data_t value;
int pos,i=0;
link_t *temp=L->next;
puts("input postion:");
scanf("%d",&pos);
if(0>pos){
puts("input error");
return -1;
}
while(i<pos){
if(NULL==temp){ //如果位置越界退出
puts("postion out link!");
return -1;
}
i++;
temp=temp->next;
}
puts("input data:");
scanf("%d",&i);
link_t *temp_2=create();
temp_2->data=i;
temp_2->next=temp->next;
temp->next=temp_2;
return 0;
}
此处在主函数中先进行了循环尾部插入,然后调用了两次任意位置插入和打印函数,这种插入是在输入位置的后一位插入,如第二次输入,也可以在尾部进行插入。
头部删除
/*
* 函数名称:headdel
* 函数功能:删除链表头部数据
* 返回值:无数据返回-1,成功返回0
*/
int headdel(link_t *L){
if(NULL==L->next){ //判断链表是否有数据
puts("none data!");
return -1;
}
link_t *temp=L->next->next;
L->next->next=NULL;
free(L->next);
L->next=temp;
return 0;
}
在主函数中还是循环尾部输入,然后调用一次头部删除。
尾部删除
删除链表尾部的一个数据,上一个链表指向NULL
/*
* 函数名称:taildel
* 函数功能:删除尾部数据
* 返回值:无数据返回-1,成功返回0
*/
int taildel(link_t *L){
if(NULL==L->next){ //判断链表是否有数据
puts("none data!");
return -1;
}
link_t *temp=L;
while(NULL!=temp->next->next){
temp=temp->next;
}
link_t *temp_2=temp->next;
free(temp_2);
temp_2=NULL;
temp->next=NULL;
return 0;
}
删除后打印结果如下
任意位置删除
输入位置判断输入是否合法后,删除指定位置的数据。
/*
* 函数名称:anydel
* 函数功能:输入位置删除
* 返回值:位置越界或在最后一位返回-1,成功返回0
*/
int anydel(link_t *L){
if(NULL==L->next){ //无数据
puts("none data");
return -1;
}
int pos,i=0;
link_t *temp=L;
puts("input postion:");
scanf("%d",&pos);
if(0>pos){
puts("input error");
return -1;
}
while(i<pos){ //要保留删除位的上一位地址,方便指向删除位下一位
temp=temp->next;
if(NULL==temp){ //如果位置越界退出
puts("postion out link!");
return -1;
}
i++;
}
if(NULL==temp->next){
puts("postion out link");
return -1;
}
link_t *temp_2=temp->next;
temp->next=temp_2->next;
temp_2->next=NULL;
free(temp_2);
temp_2=NULL;
return 0;
}
在主函数中调用三次,分别删除第一位和最后一位还有最后一个的后一位。
任意位置查找
/*
* 函数名称:anyshow
* 函数功能:查找任意位并打印
* 返回值:越界返回-1,成功返回0
*/
int anyshow(link_t *L){
if(NULL==L->next){
puts("none data!");
return -1;
}
puts("input postion:");
int pos,i=0;
link_t *temp=L->next;
scanf("%d",&pos);
if(0>pos){
puts("input error");
return -1;
}
while(i<pos){
if(NULL==temp){
puts("out link!");
return -1;
}
temp=temp->next;
i++;
}
if(NULL==temp){
puts("out link!");
return -1;
}
printf("data is %d\n",temp->data);
return 0;
}
链表数据排序
此处排序为升序,如果想要降序,只需要把比较时的符号改一下即可
/*
* 函数名称:rank
* 函数功能:根据数据大小排序
* 返回值:一个数据或无数据返回-1,成功返回0
*/
int rank(link_t *L){
if(NULL==L->next){
puts("none data");
return -1;
}
if(NULL==L->next->next){
puts("only noe data");
return -1;
}
link_t *temp=L->next;
link_t *temp_2=temp->next;
data_t t;
while(NULL!=temp->next){
while(NULL!=temp_2){
if(temp->data > temp_2->data){
t=temp->data;
temp->data=temp_2->data;
temp_2->data=t;
}
temp_2=temp_2->next;
}
temp=temp->next;
temp_2=temp->next;
}
return 0;
}
链表反转
链表中先输入的改到最后面,后输入的改到链表最前面,不是输出,而是链表中相对于表头的位置改变了,并没有出链表。