单链表的创建,添加,删除,逆置

单链表的创建,插入,删除,逆置

一 单链表:一种线性的基本数据类型,可以理解为一条长度可变的线条,中间有许多节点,节点相互之间用指针连接,连接方向从头节点至尾节点使用指针单向连接,访问也只能从头节点开始访问,尾节点的指针指向NULL。

1 单链表的创建分为主函数,输入函数,输出函数三部分。

代码:我这里是个例子

A  头插法(反向输入,先输入尾节点,再反向输入,最后一个节点为头节点):输入某个人的姓名年龄,输出

#include<stdio.h>
#include<stdlib.h>
typedef struct Student//定义链表
{
struct Student *next;
char name[20];
int age;
 }student;
student* input(student *head);//输入链表
student* scanf_(student *x);//单个节点的输入
student* print(student *head);//输出链表
int main()
{
student *head;
head=input(head);
print(head);
return 0;
}
student* input(student *head)
{
student *p,*q;
p=q=head=NULL;
p=(student*)malloc(sizeof(student));
p=scanf_(p);
p->next=q;
while(p->age!=999)//终止条件为999岁年龄
{
q=p;
p=(student*)malloc(sizeof(student));
p->next=q;
p=scanf_(p);

head=q;//终止后头节点为最后输入的有效节点
return head;
}
student* scanf_(student *x)
{
printf("请输入学生姓名:\n");
scanf("%s",x->name);
printf("请输入学生年龄\n");
scanf("%d",&x->age);
return x; 
}
student* print(student *head)
{
student *h;
h=head;
while(h)
{
printf("姓名:%s\n年龄:%d\n",h->name,h->age);
h=h->next;
}

}

/////////////////////////////

B  尾插法:输入学生的姓名,学号,年龄,成绩

//创建链表 (以下的添加,删除,逆置以此程序为源程序)


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int n=0;


typedef struct Student //定义链表
{
char name[20];
char num[10];
int age;
int score;
struct Student *next;
}student;
student* input(student *head);//输入链表
student* scanf_(student *p);//输入某节点的内容
student* output(student *head);输出链表
int main()
{
student *head,*one;
head=input(head);
output(head);
return 0;
}student* input(student *head)
{
student *p1,*p2;
p1=p2=head=NULL;
p1=(student*)malloc(sizeof(student));
scanf_(p1);
if(p1->age==0)//终止输入条件:年龄0
return NULL;
else
{
while(p1->age!=0)
{
n++;
if(n==1)//头节点单独记录
head=p1;
else
p2->next=p1;
p2=p1;
p1=(student*)malloc(sizeof(student));
scanf_(p1);
}
p2->next=NULL;

free(p1);//注意malloc的空间不free就会在程序运行期间占用内存空间
return head;
}


///////////////////////////////////////
student* scanf_(student *p)
{
student *s=p;
printf("Please input the student's name\n");
scanf("%s",s->name);
printf("Please input the student's student ID\n");
scanf("%s",s->num);
printf("Please input the student's age\n");
scanf("%d",&s->age);
printf("Please input the student's score\n");
scanf("%d",&s->score);
}


/////////////////////////////////////////
student* output(student *head)
{
int i;
student *p=head;
if(p->age==0)
printf("no one\n");
else
for(i=1;i<=n;i++)
{
printf("STUDENT No:%d:\n",i);
printf("Name:%s\n",p->name);
printf("Student ID:%s\n",p->num);
printf("Age:%d\n",p->age);
printf("Score:%d\n",p->score);
p=p->next;
}
}


///////////////////////////////////////

在完成创建后,可以对链表进行一系列的操作,函数部分除了增加对应的函数,主函数改变,程序其余函数部分不变,以下是部分操作

2 单链表的添加:

程序前面函数声明处声明函数student* add(student *newone,student *head);

////////////////////////////////
student* input(student *head);
student* scanf_(student *p);
student* output(student *head);
student* add(student *newone,student *head,int n);


/////////////////////////////

int main()//主函数部分的变化
{
student *head,*one;
head=input(head);
output(head);
printf("please input who you want to add:\n");//添加节点
one=(student*)malloc(sizeof(student));//分配空间
scanf_(one);
printf("input where you want to add:\n");//插入位置
scanf("%d",&x);
head=add(one,head,x);
output(head);//输出看链表的变化
free(one);
return 0;

}

///////////////////////

链表的输入函数,节点的输入函数,输出函数

/////////////////////////

student* add(student *newone,student *head,int x)//添加函数
{
int num=1;
student *p;
p=(student*)malloc(sizeof(student));
p=head;
if(head==NULL)//如果为空节点,直接添加为头节点
head=newone;
while(p&&num!=x)//不为空时查找位置x找到或链表到达尾节点结束
{
num++;
p=p->next;
}
newone->next=p->next;
p->next=newone;
n++;
return head;

}

//////////////////////////////

3 链表的删除:删除某个同学的信息:比对名字,相同删除

////////////////////////////////首先,声明
student* input(student *head);
student* scanf_(student *p);
student* output(student *head);
student* del(student *newone,student *head);


/////////////////////////////主函数
int main()
{
student *head,*one;
head=input(head);
output(head);
printf("please input who you want to del:\n");
one=(student*)malloc(sizeof(student));
scanf_(one);
head=del(one,head);
output(head);//输出查看
free(one);
return 0;
}

////////////////////

链表的输入函数,节点的输入函数,输出函数

////////////////////////////////////

student* del(student *newone,student *head)//删除函数
{
int t;
student *p,*q=NULL;
p=head;
if(head==NULL)//如果空链表,输出错误
{
printf("Error\n");
return NULL;
}
t=strcmp(p->name,newone->name);
if(t==0){//删除头节点,直接头节点后移一位
head=head->next;
n--;
return head;
}
while(p)
{
q=p;
p=p->next;
t=strcmp(p->name,newone->name);
if(t==0)
{
q->next=p->next;
break;
}

if(p==NULL)//没找见
{
printf("Not found\n"); 
return head;
}
n--;//节点个数减一
return head;

}

/////////////////////////////////

4 单链表的逆置

逆置认为两种,一种创建时的逆置,即头插,另一种是就地逆置,也就是在这个链表上借助临时变量头变尾,尾变头,程序如下:

////////////////////////////////
student* input(student *head);
student* scanf_(student *p);
student* output(student *head);
student* turn(student *head); //逆置函数


/////////////////////////////主函数

int main()
{
student *head,*one;
head=input(head);
output(head);
head=turn(head);
output(head);//输出查看结果
return 0;
}

////////////////////////////////////

链表的输入函数,节点的输入函数,输出函数

/////////////////////////////////

student* turn(student *head)
{
student *plast,*pnew,*ptemp;//临时变量起中转的作用
if(head->next==NULL||head==NULL)//空链表或单个节点的链表,直接返回
return head;
plast=head;//最后移动的指针
pnew=head->next;//先移动的指针(先行者),先停在第二节点处
head->next=NULL;//使头指针指向空
while(pnew)//先行者不为空时继续移动
{
ptemp=pnew;//记录之前停留的最新节点
pnew=pnew->next;//先行者移动
ptemp->next=plast;//临时节点反向存储节点的地址
plast=ptemp;//存储结束,最后移动的节点后移
}
head=plast;//当先行者为空时,代表逆置结束,临时变量所记录的节点为头节点
return head;

}

个人建议:单链表是以后学习的基础之一,试着多练习几次,找寻改正自己的错误,可以掌握的更好。

猜你喜欢

转载自blog.csdn.net/klaus_1998/article/details/80530375