(C/C++)单链表的基本操作(增删改查)
int findx(link head,datatype x);查找值为x的结点,返回结点位置
datatype findpos(link head,int i);查找在第i个位置上的结点
void insertH(link head,datatype x);头插法
void insertR(link head,datatype x,int tail);尾插法
void insertPos(link head,int i,datatype x);在指定位置插入元素
int dele(link head,int i);删除单链表第i个位置的结点
int re(link head,int i,datatype x);将位置为i的结点值修改为x
void display(link head);输出整个链表
#include<stdio.h>
typedef int datatype;
typedef struct{
datatype data;
struct node * next;
}node,*link;
//初始化一个带头结点的单链表
void init(link head){
head->next=NULL;
}
int findx(link head,datatype x){//查找值为x的结点,返回结点位置
node *p=head->next;
int count=1;
while(p&&p->data!=x){
p=p->next;
++count;
}//此循环结束 只能是链表循环结束或者找到了值为x的结点
if(p->data!=x){//说明在单链表中没有找到值为x的结点
return -1;
}
else return count;//返回值为x的结点在单链表中的位置
}
datatype findpos(link head,int i){//循找在第i个位置上的结点
int j=1;
node *p=head->next;
while(p&&j<i){
p=p->next;
j++;
}//循环结束只有两种情况,链表遍历完,但是没有找到第i个结点 ;还有一种情况就是j=i,即找到了第i个结点
if(j==i){
return p->data;//找到第i个结点,返回其节点值
}
else return -1;
}
void insertH(link head,datatype x){//头插法
node *p;
p=(node *)malloc(sizeof(node));//申请空间
p->data=x;p->next=head->next;head->next=p;
}
void insertR(link head,datatype x,int tail){//尾插法
node *p,*r;//r是尾巴
p=head;
int j=1;
//printf("%d ",tail);//验证尾结点是第几个几点是否正确
while(p&&j<tail){
p=p->next;
j++;
}//循环结束只有两种情况,链表遍历完,但是没有找到第i个结点 ;还有一种情况就是j=i,即找到了第i个结点
if(j==tail){
r=p;//刚开始链表为空时,头指针就是尾结点
p=(node *)malloc(sizeof(node));
p->data=x;r->next=p;r=p;//将结点插入链表,并将新节点设为尾指针
r->next=NULL;//最后置尾巴结点的写一个指针指向空,否则会导致链表无法结束
}
}
void insertPos(link head,int i,datatype x){//在指定位置插入元素
node *p,*q;
p=head->next;
int j=1;
while(p&&j<i-1){
p=p->next;
j++;
}//循环结束只有两种情况,链表遍历完,但是没有找到第i个结点 ;还有一种情况就是j=i-1,即找到了第i-1个结点
//printf("%d\n",p->data);//验证找到的第i个结点的前一个结点是否正确
//printf("%d\n",j); //验证找到的第i个结点的前一个结点是第几个结点是否正确
if(j==i-1){//找到了要插入位置的前一个结点,并且用p指向了它
q=(node *)malloc(sizeof(node));//申请空间
q->data=x;q->next=p->next;p->next=q;
}
}
int dele(link head,int i){//删除单链表第i个位置的结点
node *p,*q;
p=head->next;
int j=1;
while(p&&j<i-1){
p=p->next;
j++;
}//循环结束只有两种情况,链表遍历完,但是没有找到第i个结点 ;还有一种情况就是j=i-1,即找到了第i-1个结点
//printf("%d\n",j); //验证找到的第i个结点的前一个结点是第几个结点是否正确
q=p->next;//此时q指向的是要删除的结点,p指向的是其前一个结点
if(p&&q){
p->next=q->next;free(q);
return 1;
}
else return -1;
return 0;
}
int re(link head,int i,datatype x){//将位置为i的结点值修改为x
node *p,*q,*t;
if(i=1){
p=head;
q=(node *)malloc(sizeof(node));
q->data=x;//q=p->next;
t=p->next;//t指向要修改结点
q->next=t->next;//与上一句合并起来就是q->next=p->next->next;
p->next=q;
return 1;
}
p=head->next;
int j=1;
while(p&&j<i-1){
p=p->next;
j++;
}//循环结束只有两种情况,链表遍历完,但是没有找到第i个结点 ;还有一种情况就是j=i-1,即找到了第i-1个结点
//printf("i=%d,j=%d\n",i,j);
if(j==i-1){
q=(node *)malloc(sizeof(node));
q->data=x;//q=p->next;
t=p->next;//t指向要修改结点
q->next=t->next;//与上一句合并起来就是q->next=p->next->next;
p->next=q;
return 1;
}
else return -1;
}
void display(link head){//输出整个链表 ,flag用来表示是输出哪种插入方法后的链表
node *p=head->next;
while(p){
printf("%d ",p->data);
p=p->next;
}
}
void menu(){
printf("\t\t\t\t单链表基本操作目录\n");
printf("\t\t1.插入数据 2.删除数据\n");
printf("\t\t3.查找数据 4.改变某节点数据值\n");
printf("\t\t5.显示单链表中数据\n");
}
int main(){
//list L;
int choice=1;
int flag=0;//记录尾指针的位置
int find_style=1;
int dele_pos;
int re_pos,re_num,re_flag;
node head1,head2;
init(&head1);
init(&head2);
int n,num;//要插入的结点个数 ,数字
menu();
while(choice){
printf("请输入要进行的操作,输入0退出目录:\n");
scanf("%d",&choice);
switch(choice){
case 1:
printf("输入要插入的结点数:\n");
scanf("%d",&n);
printf("输入插入结点数据:\n");
while(n--){
scanf("%d",&num);
flag++;
insertH(&head1,num);
insertR(&head2,num,flag);
}
int ch_pos,num1,pos;
printf("请输入是否要进行在链表第i个结点进行数据插入:1.是 2.否\n");
scanf("%d",&ch_pos);
if(ch_pos==1){
printf("请输入要插入结点的位置:\n");
scanf("%d",&pos);
printf("输入插入结点数据:\n");
scanf("%d",&num1);
insertPos(&head1,pos,num1);//将flag传给子函数,为了方便判断该插入位置是表头,表尾还是表中
insertPos(&head2,pos,num1);
}
break;
case 2:
printf("请输入要删除结点的位置:\n");
scanf("%d",&dele_pos);
printf("头插法后的链表删除结果\n\n");
flag=dele(&head1,dele_pos);
if(flag==1)printf("删除成功\n");
else printf("删除失败\n");
printf("尾插法后的链表删除结果\n\n");
dele(&head2,dele_pos);
if(flag==1)printf("删除成功\n");
else printf("删除失败\n");
break;
case 3:
while(find_style){
printf("请输入查找方式:\n1.按值查找\n2.按节点位置查找\n0.查找结束:\n");
scanf("%d",&find_style);
if(find_style==1){
int num2,flag;
printf("请输入要查找的数值:\n");
scanf("%d",&num2);
flag=findx(&head1,num2);
printf("头插法后的链表查找结果\n\n");
if(flag==-1) printf("该单链表中不存在值为%d的结点\n",num2);
else printf("值为%d的结点是单链表中的第%d个结点\n",num2,flag);
printf("尾插法后的链表查找结果\n\n");
flag=findx(&head2,num2);
if(flag==-1) printf("该单链表中不存在值为%d的结点\n",num2);
else printf("值为%d的结点是单链表中的第%d个结点\n",num2,flag);
}
if(find_style==2){
int pos,flag;
printf("请输入要查找的结点位置:\n");
scanf("%d",&pos);
printf("头插法后的链表查找结果\n\n");
flag=findpos(&head1,pos);
if(flag==-1) printf("该单链表中不存在位置为%d的结点\n",pos);
else printf("位置为%d的结点其数值为%d\n",pos,flag);
printf("尾插法后的链表查找结果\n\n");
flag=findpos(&head2,pos);
if(flag==-1) printf("该单链表中不存在位置为%d的结点\n",pos);
else printf("位置为%d的结点其数值为%d\n",pos,flag);
}
}
break;
case 4:
printf("请输入要修改的数据位置以及数据值:\n");
scanf("%d%d",&re_pos,&re_num);
printf("头插法后的修改结果\n\n");
re_flag=re(&head1,re_pos,re_num);
if(re_flag==-1) printf("修改失败\n");
else printf("修改成功\n");
printf("尾插法后的修改结果\n\n");
re_flag=re(&head2,re_pos,re_num);
if(re_flag==-1) printf("修改失败\n");
else printf("修改成功\n");
break;
case 5:
printf("输出头插法后的单链表:\n");
display(&head1);
printf("\n");
printf("输出尾插法后的单链表:\n");
display(&head2);
printf("\n");
}
}
}