ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

单向链表的排序(使用冒泡排序交换节点)

2020-12-26 23:30:57  阅读:234  来源: 互联网

标签:struct curp 单向 冒泡排序 next 链表 nextp 链节


文章内容:

第一点:首先我们谈一谈有关链表的储存问题,首先我希望大家记住一各准则:链表的头指针尽量不要用来存储数据,为什么?因为这样会使你处理数据时更加的方便,方便在哪里?如果头指针不放数据的话,那么你在处理数据的时候,就可以将所有数据都统一对待?有的同学可能会有疑惑,结合排序说一下吧?排序的话其实就是改变各链节中的指针的指向,因为你链表的本质就是通过指针将多个链节(结构体)连接在一起,而排序就是改变链节的先后顺序,而改变它的顺序就是要改变其前后连接的的指针的指向。好讲到这里我问再回到我们最开始的问题:为什么链表的有指针不要储存数据,因为如果头指针储存数据的话,只要处理其后的指向就行,可其他的数据都要处理前后的指向关系,这就要分类讨论了,而且要考虑多很多的因素,既然如此,我干脆头指针就不储存了,这样所有的链节的处理方式都一样了。

弄懂了上面这一点后我们再来重头戏:有关排序的内容

有关链表冒泡排序的理解

首先上面也提及到了排序的问题,冒泡排序本值就是相邻比较大数(小数)后移,比较也就是说有两个物体才有比较,所以这里我们引入两个链节curp(当前链节),nextp(后一项链节),其中nextp=curp->next;因为相邻麻,如果是在数组中就就是这俩个兄弟的事情了,可这里是链表啊,你想像一下一群小朋友手拉手的情景,所以curp这个小朋友前面有人拉着它啊,所以这里再引入以个变量prep(前一项链节),还有后面的小朋友,因为是单项链表所以,干脆就认为它是nextp->next就算了;

上面说明了:我们改变链表中某两个链节的顺序问题,其实涉及到了4个链节(改变一支手拉这手的队伍中,某两个小朋友的顺序,需要改变4个小朋友的手拉手问题)

理解了上面之后其实就好办多了,下面是本人的手绘图解,帮助大家更好的理解:
在这里插入图片描述
下面上代码:
在代码中会对链表的生成及冒泡排序进行详细的解说:

#include <stdio.h>
#include <stdlib.h>
struct student
{
	int num;
	int age;
	struct student* next;
};
struct student *head = (struct student *)malloc(sizeof(struct student));
//因为链表头不储存数据,所以单独生成链表头
void main()
{
	void mppx();//自定义一个冒泡排序函数
	void addlb(struct student *pnew);//这个函数用于将生成的链节加到链表上去
	void creatlb();//该函数用于生成链节,并输入链节的数据
	void browse();//浏览个链节的内容
	head->next = NULL;//刚开始时链表只有头链节,所以head->next = NULL;
	creatlb();//函数调用生成链节,函数中会嵌套调用addlb
	mppx();//调用冒泡排序对链表进行排序
	browse();//输出链表
}

void addlb(struct student *pnew)
{
	struct student* p2;
	for (p2 = head;p2->next != NULL;p2 = p2->next)
	{
	//这个循环的目的是找出链表中的最后一个链节,方便在其后添加链节
	}
	p2->next = pnew;//添加传递过来的链节
	pnew->next = NULL;//使最后的链节的指向为NULL
}

void creatlb()//生成链节的同时输入数据
{
	int xh;
	struct student* p;
	printf("输入学生的学号(输入-1退出输入):");
	scanf("%d", &xh);
	while (xh != -1)
	{
		if ((p = (struct student*)malloc(sizeof(struct student))) == NULL)
		{
			free(p);
			break;
		}
		else
		{
			p->num = xh;
			printf("输入学生的年龄:");
			scanf("%d", &p->age);
			addlb(p);
		}
		printf("输入学生的学号(输入-1退出输入):");
		scanf("%d", &xh);
	}
}
void browse()
{
	struct student* p;
	for (p = head->next;p != NULL;p = p->next)//因为首链节head不储存数据所以从head->next开始,输出数据
	{
		printf("学生的学号:%d  学生的年龄:%d\n", p->num, p->age);
	}
	getchar();
	getchar();
}
void mppx()//重头戏,认真看
{
	struct student* prep; //prep前一项 curp当前项 nextp后一项 end控制循环
	struct student* nextp;
	struct student* end = NULL;//最开始一轮是所有的元素都要比较,所以end最开始为空
	struct student* curp;
	while (head->next != end)//冒泡排序都是双重循环,这里为外循环用于控制
	{//循环的趟数
		//初始化三个指针 ; 判断是否到达结束位置 ; 三个指针集体后移
		for (prep = head, curp = prep->next, nextp = curp->next; nextp != end; prep = prep->next, curp = curp->next, nextp = nextp->next)
		{
			if (curp->num > nextp->num) //从小到大
			{
				prep->next = nextp;//交换指针指向
				curp->next = nextp->next;
				nextp->next = curp;
				//此时next变前一项,cur变后一项  交换next cur
				struct student* temp = curp; curp = nextp; nextp = temp;
				//上面这一步我也想了很久,不是改变指针指向,就已经改变
				//顺序,这步用来干嘛呀?很好,这时请看看for循环中的循环
				//条件,并结合上图好好理解下,因为curp,nextp,都要不断后移,所以交换顺序后,
				//应该使原本的curp变为nextp,nextp=curp;
			}
		}
		//一轮循环结束 最后一项已经排好 end提前一项 (冒泡原理)
		end = curp;//此时curp就是倒数第i项。i表示内循环执行的次数
	}
}

看到这里恭喜你已经掌握了该方法,如果还是看不懂建议多看几遍,因为本文应该是csdn中相对详细的文章了

标签:struct,curp,单向,冒泡排序,next,链表,nextp,链节
来源: https://blog.csdn.net/weixin_48342617/article/details/111769542

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有