基于c语言链表上的两种排序操作

这是我在用c语言写学生管理系统时,想将录入的学生信息进行总分排序,所想出的两种排序方法。冒泡排序的大体思路就是先遍历记录结点总数n,然后做n次循环,每次找出链表中总分最高的学生结点,然后将他们依次尾插于新结点,然后再将原结点总分清零,这样就不会再次影响后续的寻找过程。这是一种基于新链表操作的排序方式。时间复杂度n²,空间复杂度n。

//冒泡排序(新建链表实现)
Student* sort(Student *head){                 
	Student *s, *p, *new, *end;
	int i = 1, j = 1;
	int max = 0;
	int mark;

	//创建新链表头结点,尾结点
	new = (Student *)malloc(sizeof(Student));
	new->next = NULL;
	end = (Student *)malloc(sizeof(Student));
	s = (Student *)malloc(sizeof(Student));

	s = head->next;

	while (s->next){
		s = s->next;
		j++;
	}
	while (j){
		s = head;
		mark = 0;
		i = 1;
		//遍历找到总分最高的结点
		while (1){
			s = s->next;
			if (s->add > max){
				max = s->add;
				mark = i;
			}
			if (s->next == NULL)
				break;
			//记录最高分所在结点数
			i++;
		}
		//指针移向总分最高的结点
		s = head;
		while (mark){
			mark--;
			s = s->next;

		}
		//将原结点移植到新链表的活动指针当中
		p = (Student *)malloc(sizeof(Student));
		for (i = 0; i < 10; i++)
			p->name[i] = s->name[i];
		p->number = s->number;
		p->math = s->math;
		p->chinese = s->chinese;
		p->english = s->english;
		p->add = s->add;
		//将原结点总分清零
		s->add = 0;
		//对于结点插入新链表
		if (new->next == NULL){
			new->next = p;
			end = p;
			end->next = NULL;
		}
		else{
			end->next = p;
			end = p;
			end->next = NULL;
		}
		j--;
		//比较值清零
		max = 0;
	}
	return new;
}

选择排序的大体思想就是先依次遍历找出结点总数n,利用两个活动指针,一个做标志记录无序结点开始位置,一个做遍历结点的指针,然后做n次循环,每次找到总分最高的结点,然后和最前面的记录指针的结点做数据交换,这个不需要开辟新链表,虽然时间复杂度依旧是n²,但是空间复杂度为1。
//选择排序(原列表操作)
Student* sort(Student *head){
Student *s,*p,*temp;
int i = 1,j=0;
int max = 0;
int mark;

//创建新链表交换结点,
temp = (Student *)malloc(sizeof(Student));
temp->next = NULL;

s = (Student *)malloc(sizeof(Student));
s->next = NULL;

p = (Student *)malloc(sizeof(Student));
p->next = NULL;

p = head->next;
s = p;
//判断链表的长度
while (s->next){
	s = s->next;
	j++;
}
//开始排序
while (j){
	s = p;
	mark = 0;
	max = 0;
	i = 0;
	//遍历找到总分最高的结点
	while (1){
		if (s->add > max){
			max = s->add;
			mark =i;
		}
		if (s->next == NULL)
			break;
		s = s->next;
		//记录最高分所在结点数
		i++;                                             
	} 
	//指针移向总分最高的结点
	s = p;
	while (mark){
		mark--;
		s = s->next;
	}
	//双节点的数据进行交换
	for (i = 0; i < 10; i++)
		temp->name[i] = p->name[i];
	temp->number = p->number;
	temp->chinese = p->chinese;
	temp->math = p->math;
	temp->add = p->add;
	temp->english = p->english;

	for (i = 0; i < 10; i++)
		p->name[i] = s->name[i];
	p->number = s->number;
	p->chinese = s->chinese;
	p->math = s->math;
	p->add = s->add;
	p->english = s->english;

	for (i = 0; i < 10; i++)
		s->name[i] = temp->name[i];
	s->number = temp->number;
	s->chinese = temp->chinese;
	s->math = temp->math;
	s->add = temp->add;
	s->english = temp->english;
	p = p->next;
	j--;
}
	return head;

}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值