c语言数据排序法的个人总结.docx
- 文档编号:7269005
- 上传时间:2023-01-22
- 格式:DOCX
- 页数:14
- 大小:24.87KB
c语言数据排序法的个人总结.docx
《c语言数据排序法的个人总结.docx》由会员分享,可在线阅读,更多相关《c语言数据排序法的个人总结.docx(14页珍藏版)》请在冰豆网上搜索。
c语言数据排序法的个人总结
c语言数据排序法的个人总结
篇一:
C语言常用的三种排序方法总结与探讨
C语言常用的三种排序方法总结与探讨排序是程序设计中非常重要的内容,它的功能是将一组无序的的数据,排列成有序的数据序列,经过排列后的数据,要么是从大到小排列,要么是从小到大排列。
一般也只有这两种情况。
例如我们统计班级学生的成绩,那么一般是按照学号来进行统计,原来成绩是无序排列的,这样的话非常不适合于我们对成绩的查询,那么一般我们进行成绩查询之前,先进行排序,如按照高分到低分的排序,这样可以很快地查出本班的最高分和最低分,和成绩比较靠前或靠后的学生。
排序有很多种方法,常用的有三种:
冒泡排序、选择排序、插入排序等,下面我们就对这三种方法做一下分析和比较,以便大家能够更好的理解和应用。
一、冒泡排序
1、冒泡排序的基本思想:
对于n个数进行排序(现假定是从大到小排序,以下均按此进行),将相邻两个数依次比较,将大数调在前头:
也就是说第一个数和第二个数比较,大数放前,小数放后,第二个和第三个进行比较,大数放前、小数放后,然后依次类推。
。
。
经过第一轮比较以后,我们找到一个最小数在最下面(沉底)。
然后进行下一轮比较,最后一个数就不用再参加比较了,所以本轮就可以少比较一次。
很显然,需要用双重循环来设计这个问题,外层循环控制进行的轮数,内层循环控制每轮比较的次数,那么到底需要多少轮、
每轮需要多少次,我们通过一个实例看一下:
3、冒泡排序的程序如下:
for
for
if
{t=a[j];a[j]=a[j+1];a[j+1]=t;}
在此程序段的上面加上输入部分和在程序段加上排序后的输出。
程序的改进:
4、算法的改进:
从上面的排序的过程可以看出,如果一个已经排好序的一组数或者经过很少的轮数就可以排完这些数,但是循环还是要继续进行,这样设计出的程序浪费了大量的时间,所以对一这个算法我们可以重新设计。
经过修改后的程如下:
for
{
swap=1;
for
if
{t=a[j];a[j]=a[j+1];a[j+1]=t;swap=0;}
}
二、选择排序
1、排序的基本思想:
先从第一个数开始起,用第一个数和其它的数进行比较,如果比第一个数大就交换位置,否则不进行交换,这样经过第一轮比较我们就能够找出最大值放在第一位置,然后从第二个位置起再找次大数,这样依次下去,就可以进行整个数的排序,实践证明,n个数最多需要n-1轮排序就可以了。
选择排序较冒泡容易理解,程序编写也要相对容易一些。
for
for
if
{t=a[i];a[i]=a[j];a[j]=t;}
对于选择排序,我们也可以看到一个问题,如第一轮排序中,我们要找的是9才是最大值,所以其它的交换完全没有必要进行,其它各轮都存在这样的情况,所以我们可以想办法取消这种情况,也就是说我们
真正找到的最大值的位置后再进行交换。
for
{p=i;
for
if
p=j;
if
{t=a[i];a[i]=a[j];a[j]=t;}
}
这样算法经过改进以后就较好地解决了这个问题。
三、插入排序
1、插入排序基本思想:
(假定从大到小排序)依次从后面拿一个数和前面已经排好序的数进行比较,比较的过程是从已经排好序的数中最后一个数开始比较,如果比这个数,继续往前面比较,直到找到比它大的数,然后就放在它的后面,如果一直没有找到,肯定这个数已经比较到了第一个数,那就放到第一个数的前面。
那么一般情况下,对于采用插入排序法去排序的一组数,可以先选取第一个数做为已经排好序的一组数。
然后把第二个放到正确位置
2、程序的编写如下:
for//i从0开始或者1开始都可以。
其它不变。
for
if
{t=a[j];a[j]=a[j-1];a[j-1]=t;}
对于这个程序也有需要修该的地方,以上程序的排序实际上也是基于交换思想进行排序,也可以进行真正意义上的排序,即:
先把待排序的数取出来,然后找出应该插入的位置,找到后,将待插入位置后的数据统统后移,原待排数据已经取出放于临时变量中。
然后把这个数据插入到正确的空余位置就可以了。
那么对于基于交换的插入排序,没有找到位置之前,也进行了交换,所以我们也可以进行程序的改进。
那么此程序的改进,肯定不能进行减少交换次数,因为我们知道如果到找到位置再进行交换,那么肯定已经找乱了原来的排序结果,所以只能是找位置,腾位置、放元素这几道手续。
main
{
inti,j,t,a={12,11,2,3,6,67,89,0,1,3};
for
{t=a[i];
j=i-1;
while
{a[j+1]=a[j];
j--;
}
a[j+1]=t;
}
篇二:
C语言排序方法总结
C语言排序方法
学的排序算法有:
插入排序,合并排序,冒泡排序,选择排序,希尔排序,堆排序,快速排序,计数排序,基数排序,桶排序(没有实现)。
比较一下学习后的心得。
我不是很清楚他们的时间复杂度,也真的不知道他们到底谁快谁慢,因为书上的推导我确实只是小小了解,并没有消化。
也没有完全理解他们的精髓,所以又什么错误的还需要高手指点。
呵呵。
1.普及一下排序稳定,所谓排序稳定就是指:
如果两个数相同,对他们进行的排序结果为他们的相对顺序不变。
例如A={1,2,1,2,1}这里排序之后是A={1,1,1,2,2}稳定就是排序后第一个1就是排序前的第一个1,第二个1就是排序前第二个1,第三个1就是排序前的第三个
1。
同理2也是一样。
这里用颜色标明了。
不稳定呢就是他们的顺序不应和开始顺序一致。
也就是可能会是A={1,1,1,2,2}这样的结果。
2.普及一下原地排序:
原地排序就是指不申请多余的空间来进行的排序,就是在原来的排序数据中比较和交换的排序。
例如快速排序,堆排序等都是原地排序,合并排序,计数排序等不是原地排序。
3.感觉谁最好,在我的印象中快速排序是最好的,时间复杂度:
n*log,不稳定排序。
原地排序。
他的名字很棒,快速嘛。
当然快了。
我觉得他的思想很不错,分治,而且还是原地排序,省去和很多的空间浪费。
速度也是很快的,n*log。
但是有一个软肋就是如果已经是排好的情况下时间复杂度就是n*n,不过在加入随机的情况下这种情况也得以好转,而且他可以做任意的比较,只要你能给出两个元素的大小关系就可以了。
适用范围广,速度快。
4.插入排序:
n*n的时间复杂度,稳定排序,原地排序。
插入排序是我学的第一个排序,速度还是很快的,特别是在数组已排好了之后,用它的思想来插入一个数据,效率是很高的。
因为不用全部排。
他的数据交换也很少,只是数据后移,然后放入要插入的数据。
(这里不是指调用插入排序,而是用它的思想)。
我觉得,在数据大部分都排好了,用插入排序会给你带来很大的方便。
数据的移动和交换都很少。
5.冒泡排序,n*n的时间复杂度,稳定排序,原地排序。
冒泡排序的思想很不错,一个一个比较,把小的上移,依次确定当前最小元素。
因为他简单,稳定排序,而且好实现,所以用处也是比较多的。
还有一点就是加上哨兵之后他可以提前退出。
6.选择排序,n*n的时间复杂度,稳定排序,原地排序。
选择排序就是冒泡的基本思想,从小的定位,一个一个选择,直到选择结束。
他和插入排序是一个相反的过程,插入是确定一
个元素的位置,而选择是确定这个位置的元素。
他的好处就是每次只选择确定的元素,不会对很多数据进行交换。
所以在数据交换量上应该比冒泡小。
7.插入排序,选择排序,冒泡排序的比较,他们的时间复杂度都是n*n。
我觉得他们的效率也是差不多的,我个人喜欢冒泡一些,因为要用它的时候数据多半不多,而且可以提前的返回已经排序好的数组。
而其他两个排序就算已经排好了,他也要做全部的扫描。
在数据的交换上,冒泡的确比他们都多。
呵呵。
举例说明插入一个数据在末尾后排序,冒泡只要一次就能搞定,而选择和插入都必须要n*n的复杂度才能搞定。
就看你怎么看待咯。
8.合并排序:
n*log的时间复杂度,稳定排序,非原地排序。
他的思想是分治,先分成小的部分,排好部分之后合并,因为我们另外申请的空间,在合并的时候效率是0的。
速度很快。
貌似他的上限是n*log,所以如果说是比较的次数的话,他比快速排序要少一些。
对任意的数组都能有效地在n*log排好序。
但是因为他是非原地排序,所以虽然他很快,但是貌似他的人气没有快速排序高。
9.堆排序:
n*log的时间复杂度,非稳定排序,原地排序。
他的思想是利用的堆这种数据结构,堆可以看成一个完全二叉树,所以在排序中比较的次数可以做到很少。
加上他也是原地排序,不需要申请额外的空间,效率也不错。
可是他的思想感觉比快速难掌握一些。
还有就是在已经排好序的基础上添加一个数据再排序,他的交换次数和比较次数一点都不会减少。
虽然堆排序在使用的中没有快速排序广泛,但是他的数据结构和思想真的很不错,而且用它来实现优先队列,效率没得说。
堆,还是要好好学习掌握的。
10.希尔排序:
n*log的时间复杂度,lamda和每次步长选择有关。
),非稳定排序,原地排序。
主要思想是分治,不过他的分治和合并排序的分治不一样,他是按步长来分组的,而不是想合并那样左一半右一半。
开始步长为整个的长度的一半。
分成nLen/2个组,然后每组排序。
接个步长减为原来的一半在分组排序,直到步长为1,排序之后希尔排序就完成了。
这个思路很好,据说是插入排序的升级版,所以在实现每组排序的时
候我故意用了插入排序。
我觉得他是一个特别好的排序方法了。
他的缺点就是两个数可能比较多次,因为两个数据会多次分不过他们不会出现数据的交换。
效率也是很高的。
11.快速排序,堆排序,合并排序,希尔排序的比较,他们的时间复杂的都是n*log,我认为在使用上快速排序最广泛,他原地排序,虽然不稳定,可是很多情况下排序根本就不在意他是否稳定。
他的比较次数是比较小的,因为他把数据分成了大和小的两部分。
每次都确定了一个数的位置,所以理论上说不会出现两个数比较两次的情况,也是在最后在交换数据,
说以数据交换上也很少。
合并排序和堆排序也有这些优点,但是合并排序要申请额外的空间。
堆排序堆已经排好的数据交换上比快速多。
所以目前快速排序用的要广泛的多。
还有他很容易掌握和实现。
12.计数排序:
n的时间复杂度,稳定排序,非原地排序。
他的思想比较新颖,就是先约定数据的范围不是很大,而且数据都是整数的情况,然后直接申请一个空间。
把要排序的数组A的元素值与申请空间B的下标对应,然后B中存放该下标元素值的个数,从而直接定位A中每个元素的位置。
这样效率只为n。
因为比较很特殊,虽然很快,但是用的地方并不多。
13.基数排序:
n的时间复杂度,稳定排序,非原地排序。
他的思想是数据比较集中在一个范围,例如都是4位数,都是5位数,或数据有多个关键字,我们先从各位开始排,然后排十位,依次排到最高位,因为我们可以用一个n的方法排一位,所以总的方法为d*n的复杂度。
关键字也一样,我们先排第3个关键字,在排第3个关键字,最后排第一个关键字。
只有能保证每个关键字在n的时间复杂度完成,那么整个排序就是一个d*n的时间复杂度。
所以总的速度是很快的。
不过有一点就是要确保关键字能在n的时间复杂度完成。
14.桶排序:
n的时间复杂度,稳定排序,非原地排序。
主要思路和基数排序一样,也是假设都在一个范围例如概率都在0-1,而且分布还挺均匀,那么我们也是和基数排序一样对一个数把他划分在他指定的区域。
然后在连接这些区域就可以了。
书上对每个区域使用链表的存储,我认为在寸小区域的时候也会有时间在里面。
所以只是理论上的n时间复杂度。
这种思路是不错的。
呵呵。
15.计数排序,基数排序,桶排序的比较,我觉得他们都很有思想,不过都是在特定情况下才能发挥最大的效果。
虽然效率很高,但是用的不会很广泛。
他们之间我更喜欢计数排序,来个映射的方式就直接找到了自己的位置,很高明。
和基数排序和同排序只是理论上的n时间复杂度,基数排序要确定一个关键字的排序是n复杂度的,桶排序要确定每个区域的排序是n复杂度的。
16.排序算法的最后感悟:
黑格尔说过:
存在即合理。
所以这些排序的算法都是很好的,他确实给了我们思想上的帮助。
感谢前人把精华留给了我们。
我得到的收获很大,总结一下各自排序的收获:
冒泡:
好实现,速度不慢,使用于轻量级的数据排序。
插入排序:
也使用于小数据的排序,但是我从他的思想中学到怎么插入一个数据。
呵呵,这样就知道在排好的数据里面,不用再排序了,而是直接调用一下插入就可以了。
选择排序:
我学会了怎么去获得最大值,最小值等方法。
只要选择一下,不就可以了。
合并排序:
我学会分而治之的方法,而且在合并两个数组的时候很适用。
堆排序:
可以用它来实现优先队列,而且他的思想应该给我加了很多内力。
快速排序:
本来就用的最多的排序,对我的帮助大的都不知道怎么说好。
希尔排序:
也是分治,让我看到了分治的不同,原来还有这种思想的存在。
计数排序,基数排序,桶排序:
特殊情况特殊处理。
插入排序
插入排序主要思想是:
把要排序的数字插入到已经排好的数据中。
例如12356是已经排好的序,我们将4插入到他们中,时插入之后也是排好序的。
这里显而易见是插入到3的后面。
变为123456.实现思路:
插入排序就是先是一个有序的数据,然后把要插入的数据插到指定的位置,而排序首先给的就是无序的,我们怎么确定先得到一个有序的数据呢?
答案就是:
如果只有一个,当然是有序的咯。
我们先拿一个出来,他是有序的,然后把数据一个一个插入到其中,那么插入之后是有序的,所以直到最后都是有序的。
。
结果就出来了!
当然在写的时候还是有一个技巧的,不需要开额外的数组,下标从第二个元素开始遍历知道最后一个,然后插入到前面已经有序的数据中。
这样就不会浪费空间了。
插入排序用处还是很多的,特别是链表中,因为链表是指针存放的,没有数组那么好准确的用下标表示,插入是简单有效的方法。
源代码
1#include
2#include
3
4//插入排序从下到大,nData为要排序的数据,nNum为数据的个数,该排序是稳定的排序5boolInsertionSort
6{
7for//遍历数组,进行插入排序
8{
9intnTemp=nData[i];
10for//对该数,寻找他要插入的位置
11{
12if//找到位置,然后插入该位置,之后的数据后移13{
14for//数据后移
15{
16nData[k]=nData[k-1];
17}
18nData[j]=nTemp;//将数据插入到指定位置
19break;
20}
21}
22}
23
24returntrue;
25}
26
27intmain
28{
29intnData[10]={4,10,9,8,7,6,5,4,3,2};//创建10个数据,测试30InsertionSort;//调用插入排序
31
32for
33{
34printf;
35}
36
37printf;
38system;
39return0;
40}
篇三:
C语言中三种常见排序算法分析
C语言中三种常见排序算法分析
一、冒泡法(起泡法)
算法要求:
用起泡法对10个整数按升序排序。
算法分析:
如果有n个数,则要进行n-1趟比较。
在第1趟比较中要进行n-1次相邻元素的两两比较,在第j趟比较中要进行n-j次两两比较。
比较的顺序从前往后,经过一趟比较后,将最值沉底(换到最后一个元素位置),最大值沉底为升序,最小值沉底为降序。
算法源代码:
#include
main
{
inta[10],i,j,t;
printf;
/*输入源数据*/
for
scanf;
/*排序*/
for/*外循环控制排序趟数,n个数排n-1趟*/
for/*内循环每趟比较的次数,第j趟比较n-j次*/
if/*相邻元素比较,逆序则交换*/
{t=a[i];
a[i]=a[i+1];
a[i+1]=t;
}
/*输出排序结果*/
printf;
for
printf;
printf;
}
算法特点:
相邻元素两两比较,每趟将最值沉底即可确定一个数在结果的位置,确定元素位置的顺序是从后往前,其余元素可能作相对位置的调整。
可以进行升序或降序排序。
算法分析:
定义n-1次循环,每个数字比较n-j次,比较前一个数和后一个数的大小。
然后交换顺序。
二、选择法
算法要求:
用选择法对10个整数按降序排序。
算法分析:
每趟选出一个最值和无序序列的第一个数交换,n个数共选n-1趟。
第i趟假设i为最值下标,然后将最值和i+1至最后一个数比较,找出最值的下标,若最值下标不为初设值,则将最值元素和下标为i的元素交换。
算法源代码:
#include
main
{
inta[10],i,j,k,t,n=10;
printf;
for
scanf;
for/*外循环控制趟数,n个数选n-1趟*/
{
k=i;/*假设当前趟的第一个数为最值,记在k中*/
for/*从下一个数到最后一个数之间找最值*/
if/*若其后有比最值更大的*/
k=j;/*则将其下标记在k中*/
if/*若k不为最初的i值,说明在其后找到比其更大的数*/
{t=a[k];a[k]=a[i];a[i]=t;}/*则交换最值和当前序列的第一个数*/
}
printf;
for
printf;
printf;
}
算法特点:
每趟是选出一个最值确定其在结果序列中的位置,确定元素的位置是从前往后,而每趟最多进行一次交换,其余元素的相对位置不变。
可进行降序排序或升序排序。
算法分析:
定义外部n-1次循环,假设第一个为最值,放在参数中,在从下一个数以后找最值若后面有比前面假设的最值更大的就放在k中,然后在对k进行分析。
若k部位最初的i值。
也就是假设的i不是最值,那么就交换最值和当前序列的第一个数
三、插入法
算法要求:
用插入排序法对10个整数进行降序排序。
算法分析:
将序列分为有序序列和无序列,依次从无序序列中取出元素值插入到有序序列的合适位置。
初始是有序序列中只有第一个数,其余n-1个数组成无序序列,则n个数需进n-1次插入。
寻找在有序序列中插入位置可以从有序序列的最后一个数往前找,在未找到插入点之前可以同时向后移动元素,为插入元素准备空间。
算法源代码:
#include
main
{
inta[10],i,j,t;
printf;
for
scanf;
for/*外循环控制趟数,n个数从第2个数开始到最后共进行n-1次插入*/
{
t=a[i];/*将待插入数暂存于变量t中*/
for/*在有序序列(下标0~i-1)中寻找插入位置*/
a[j+1]=a[j];/*若未找到插入位置,则当前元素后移一个位置*/
a[j+1]=t;/*找到插入位置,完成插入*/
}
printf;
for
printf;
printf;
}
四、两路归并
main
{
inta[3]={5,9,10};
intb[5]={12,24,26,37,48};
intc[10],i,j,k;
i=j=k=0;
while
{if
{c[k]=b[j];
k++;
j++;
}
else
{
c[k]=a[i];
k++;
i++;
}
while
{c[k]=a[i];
i++;
k++;
}
while
{c[k]=b[j];
j++;
k++;
}
forprintf;
}
算法特点:
每趟从无序序列中取出第一个数插入到有序序列的合适位置,元素的最终位置在最后一趟插入后才能确定位置。
也可是先用循环查找插入位置(可从前往后或从后往前),再将插入位置之后的元素(有序列中)逐个后移一个位置,最后完成插入。
该算法的特点是在寻找插入位置的同时完成元素的移动。
因为元素的移动必
须从后往前,则可将两个操作结合在一起完成,提高算法效率。
仍可进行升序或降序排序。
几种排序的概念
在数据的处理中,数据的排序是相当重要的。
它可以使数据更有条理,方便数据的其它处理。
在学习生活中,也经常用到数据的排序,如:
考完试后个人成绩的排名、运动会上班级总分的排名、常规评比分数的排序。
这些排序当然不是人工完成的,它们大多数是用excel软件来代劳的。
那么excel软件的排序的本质方法是什么呢?
这就是我所要研究学习的内容。
通过查阅图书、教材,搜索资料、教程,我了解到:
排序的本质其实就是比较。
对于任何一种排序方法来说,比较都是其最重要的一个组成部分。
但它也是最简单的部分,因为排序方法的好坏、快慢取决于比较的方法、比较的顺序和比较的次数,而与比较本身关系不大。
那么,排序具体有那些方法呢?
下面介绍几种我研究学习了的算法。
一、冒泡排序
已知一组无序数据a[1]、a[2]、?
?
a[n],需将其按升序排列。
首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。
再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变。
再比较a[3]与a[4],依此类推,最后比较a[n-1]与a[n]的值。
这样处理一轮后,a[n]的值一定是这组数据中最大的。
再对a[1]~a[n-1]以相同方法处理一轮,则a[n-1]的值一定是a[1]~a[n-1]中最大的。
再对a[1]~a[n-2]以相同方法处理一轮,依此类推。
共处理n-1轮后a[1]、a[2]、?
?
a[n]就以升序排列了。
优点:
稳定,比较次数已知;
缺点:
慢,每次只能移动相邻两个数据,移动数据的次数多。
二、选择排序
已知一组无序数据a[1]、a[2]、?
?
a[n],需将其按升序排列。
首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。
再比较a[1]与a[3]的值,若a[1]大于a[3]则交换两
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 数据 排序 个人 总结