C++链表综合操作

链表的开辟空间、输出链表、插入、删除

/**
链表综合操作
*/
#define LEN sizeof(struct student)
//建立动态链表
struct student{
	int num;
	float score;
	struct student *next;
};
int n;

//定义一个开辟空间的方法
struct student *creat(void){
	struct student *head,*p1,*p2;
	n=0;
	p1=p2=(struct student *)malloc(LEN);   //开辟一个空间,p1,p2都指向那个空间
	scanf("%ld,%f",p1->num,p1->score);    //给空间输入值
	head=NULL;    //头节点没有值
	while(p1->num!=0){    //判断什么时候输入学生的学号为0了,就停止
		n=n+1;    //n代表输入第几个学生,或者开辟的第几个空间
		if(n==1){    //如果n=1,表示是第一次开辟空间
			head=p1;    //让头节点指向第一个空间
			p2->next=p1;     //让第一个空间的next为p1,方便利用p1接着开辟新的空间
		}
		p2=p1;   //让p2也和p1相等   继续开辟空间
		p1=(struct student *) malloc(LEN);  // p1开辟空间
		scanf("%ld,%f",p1->num,p1->score);    //给p1这个空间赋值
	}
	p2->next=NULL;   //最后一个学生信息输入完了,尾指针让他为空
	free(p1);   //此时,p1已经不用了,所以释放它最后一次开辟的空间
	return(head);   //返回头指针
}

//删除链表某个节点
struct student *del(struct student *head,long num){
	struct student *p1,*p2;                         //定义两个结构体指针变量
	if(head==NULL){                           //判断要删除的链表是否为空
		printf("链表是空的\n"); goto end;   //如果为空,输出结果,直接返回
	}
	p1=head;                    //不为空的话,让p1等于head
	while(num!=p1->num && p1->next!=NULL){      //判断p1里面的num和要删除的num是否相同,并且p1的next指针不为空
		p2=p1;p1=p1->next;           //如果p1的num和要删除的num不相同,让p2=p1,p1移向下一个结点
	}
	if(num==p1->num){               //当要删除的num和p1的num相同时,跳出循环,执行这里
		if(p1==head){               //判断要删除的结点是不是第一个结点(头结点)
			head=p1->next;          //如果是头节点,让头结点为第二个结点
		}else{
			p2->next=p1->next;    //如果不是,让p2的next指针指向p1的next指针,这样就跳过了num结点
		}
		printf("已删除:第%ld个节点\n",num);
		n=n-1;
	}else{
		printf("%ld节点没有找到\n",num);   //如果最后p1的next为空了,并且num也没找到,那么提示该结点没找到
	}
	end:return(head);
}


//插入某个结点
struct student *insert(struct student *head,struct student *stu){
	struct student *p0,*p1,*p2;    //定义三个结构体指针变量
	p1=head;p0=stu;       //让头结点等于p1,p0为要加入的结点
	if(head==NULL){     //如果头指针是空的,说明链表为空
		head=p0;    //直接让p0为头指针
		p0->next=NULL;    //让p0的下一个结点为空
	}else{      //如果头结点不为空,说明链表有结点
		while((p0->num>p1->num)&&(p1->next!=NULL)){     //判断要加入的p0结点的num是否大于p1的num,并且p1的下一个结点不为空
			p2=p1;p1=p1->next;        //如果大于且不为空,让p2=p1,p1指向下一个结点,说明p0不应该插在比p1大的地方
		}
		if(p0->num<=p1->num){              //p0的num小于等于p1的num
			if(head==p1){                  //如果正好头结点为p1
				head=p0;                   //就让p0为头结点,查找第一个
			}else{                          //如果不是
				p2->next=p0;           //让p2的下一个结点为p0
				p0->next=p1;           //让p0的下一个结点为p1
			} 
		}else{
			p1->next=p0;p0->next=NULL;   //如果p0的num就是大于p1的num,但是p1的下一个结点为空
			//,说明p0要插在最后一个结点的下一个,并且p0之后没结点了,所以p0->next必须为空
		}
	}
	n=n+1;   //插入了一个,链表个数+1
	return(head);
}
//输入链表
void print(struct student *head){
	struct student *p;
	printf("这%d个记录是:\n",n);
	p=head;
	if(head!=NULL){
		do{
			printf("%ld%5.1f\n",p->num,p->score);
			p=p->next;
		}while(p!=NULL);
	}
}


//综合操作  删除、插入操作只可进行一次
int main(){
	struct student *head,stu;
	long del_num;   //定义一个结构体指针变量,定义一个stu结构体 和一个del_num长整型变量
	printf("输出结点个数:\n",n);    //输出现有的结点个数
	head=creat();     //开辟新的空间
	print(head);      //输出新开辟的链表
	printf("输入要删除的结点num:\n");    
	scanf("%d",del_num);     //输入要删除的结点
	head=del(head,del_num);     //调用删除结点函数
	print(head);      //输出链表
	printf("插入已经删除的数:\n");    
	scanf("%ld&6.2f",&stu.num,&stu.score);   //将已经删除的结点重新输入,stu结构体
	head=insert(head,&stu);    //插入stu结点,此处插入的是已经删除的结点,因此有内存区,
	//如果再插入一个结点,必须先开辟一个链表空间
	print(head);   //输出链表
	system("pause");
	return 0;
}

//插入和删除可进行多次
int main(){
	struct student *head,*stu;
	long del_num;
	printf("input records:\n");
	head=creat();
	print(head);
	printf("\ninput the deleted number:");
	scanf("ld",&del_num);
	while(del_num!=0){                        //循环删除结点操作
		head=del(head,del_num);
		print(head);
		printf("input the deleted number:");
		scanf("ld",&del_num);
	}
	printf("\ninput the inserted record:");
	stu=(struct student *) malloc(LEN);
	scanf("ld,%f",&stu->num,&stu->score);
	while(stu->num!=0){                       //循环插入操作
		head=insert(head,stu);
		printf("input the inserted record:");
		stu=(struct student *) malloc(LEN);
		scanf("ld,%f",&stu->num,&stu->score);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值