带头结点的链表及菜单 2018年12月26日

带头结点的链表及菜单 2018年12月26日
以下内容仅供娱乐,欢迎随时探讨,请多指教

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
/*定义结构体*/
struct student {
	int num;
	float score;
	struct student *next;
};
/*初始化链表*/
struct student *Init_List() {
	struct student *head;
	head=(struct student*)malloc(sizeof (struct student) );
	if(head==NULL) {           //小心别漏这个
		printf("申请头结点失败!\n");
		return NULL;
	}
	head->next=NULL;
	return head;
}
/*创建带头结点的链表*/
struct student *create_head(struct student *head) {
	int sno;
	float score;
	struct student *p,*q;
	q=head;
	while(q->next) q=q->next;
	printf("请输入学号和成绩,学号输入-1结束: ");
	scanf("%d%f",&sno,&score);
	while(sno>=0) {
		p=(student *)malloc(sizeof(student));
		p->num=sno;
		p->score=score;
		q->next=p;
		q=p;
		scanf("%d%f",&sno,&score);
	}
	q->next=NULL;
	return head;
}
/*将s指向的结点插入链表,使链表保持升序,并返回头结点*/
void insert(struct student *head,struct student *s) {
	struct student *p=head;
	while(p->next!=NULL&&s->score>p->next->score)//特别注意&&左右不能写反,若s最大,最后p->next=NULL,p->next->score运行出错
		p=p->next;
	if(p->next==NULL) { //s->score最大的情况     //其实两种情况可以并在一块写
		p->next=s;    //连接结点
		s->next=NULL;   //p->next就等于NULL
	} else {
		s->next=p->next;
		p->next=s;    //连接结点,这两条语句不要写反

	}
}
/*查找符合条件的结点,并返回指向该结点的指针*/
struct student * search(struct student *head,int num) {
	struct student *p=head->next;
	while(p!=NULL&&p->num!=num)   //特别注意两条件不能写反,若写反最后p指向NULL时p->num找不到 运行出错
		p=p->next;
	return p;
}
/*输出链表各结点的值,也称对链表的遍历*/
void print(struct student *head) {
	struct student *p;
	printf("  链表如下:  \n");
	p=head->next;
	while(p) {
		printf("%d\t%.1f\n",p->num,p->score);
		p=p->next;
	}
}
/*释放链表*/
void free_list(struct student *head) {
	struct student *p=head ;
	printf("释放链表:\n");
	while(p!=NULL) {
		head=head->next;
		free(p);
		p=head;
	}
	printf("释放链表成功!\n");
}
/*删除链表中值为num的结点,并返回链表的首指针*/
void delete_note(struct student *head,int num_x) {
	struct student *p1=head->next , *p2=head ;
	while(p1!=NULL&&p1->num!=num_x) { //特别注意&&左右条件不能调换,若调换如果p1指向NULL时p1->num运行出错
		p2=p1;
		p1=p1->next;
	}
	if(p1==NULL)    return;

	p2->next=p1->next;
	free(p1);

}
//获取链表长度(不包括头节点)
int Size_List(struct student* head) {
	struct student* temp = head->next;
	int size = 0;
	while (temp) {
		size++;
		temp = temp->next;
	}
	return size;
}
//链表的排序(冒泡)
void Sort_List(struct student* head) {
	int i,j, n = Size_List(head);
	struct student *p;
	int t;
	float r;
	for (i=1; i<n; i++) {
		p=head->next;
		for (j=1; j<=n-i; j++) {
			if (p->score > p->next->score) {
				t=p->num,p->num=p->next->num,p->next->num=t;
				r=p->score,p->score=p->next->score,p->next->score=r;
			}
			p=p->next;
		}
	}
}
/*完整的有头结点链表操作程序*/
int main() {
	struct student *p , *head ;
	char c;
	int num ;
	float score ;
	printf("有头结点链表操作程序:\n");
	head=Init_List();
	while(1) {
		printf("\nC:创建链表 I:插入结点(自动升序)  P:输出链表 "
		" S:查找结点  D:删除结点  X:排序 E:释放链表并退出程序! \n ");
		c=getch();
		switch(c) {
			case 'I':
			case 'i':
				printf("请分别输入要插入学生的学号和分数:\n");
				scanf("%d%f",&num,&score);
				p=(struct student*)malloc( sizeof(struct student) );
				if(p==NULL) {
					printf("申请该结点失败!!!\n");
					exit (0) ;
				}
				p->num=num;
				p->score=score;   //给p赋值
				insert(head,p);
				printf("插入成功!\n");
				break;
			case 'C':
			case 'c':
				head=create_head(head);
				break;
			case'P':
			case 'p':
				print(head);
				break;
			case'S':
			case 's':
				printf("输入要查找的学号\n");
				scanf("%d",&num);
				p=search(head,num);
				if (p) {
					printf("该学生信息为: ");
					printf("num=%d,score=%f\n",p->num,p->score);
				} else
					printf("该学生不存在\n");
				break;
			case'D':
			case 'd':
				printf("请输入要删除的学生的学号:\n");
				scanf("%d",&num);
				delete_note(head,num);
				break;
			case 'X':
			case 'x':
				Sort_List(head);
				break;
			case 'E':
			case 'e':
				free_list(head);
				exit (0);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43310774/article/details/85270018