(C/C++)单链表的基本操作(增删改查)

(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");
		}
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值