排序.docx

上传人:b****5 文档编号:4104636 上传时间:2022-11-27 格式:DOCX 页数:29 大小:68.78KB
下载 相关 举报
排序.docx_第1页
第1页 / 共29页
排序.docx_第2页
第2页 / 共29页
排序.docx_第3页
第3页 / 共29页
排序.docx_第4页
第4页 / 共29页
排序.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

排序.docx

《排序.docx》由会员分享,可在线阅读,更多相关《排序.docx(29页珍藏版)》请在冰豆网上搜索。

排序.docx

排序

排序

1.排序算法优劣:

●空间复杂度:

需要的辅助内存

●时间复杂度:

关键字的比较次数以及移动次数,消耗总时间

●稳定性:

若A和B的关键字相同,但排序后A、B的先后次序保持不变,则称这种算法是稳定的;反之,则是不稳定的

2.分类

●内部排序:

整个排序过程不需要借助外部存储器,所有排序操作都在内存中完成。

●外部排序:

如果需要进行排序的数据量比较庞大,在内存中不能一次性注入所有的数据,需要借助于外部存储器,这样的排序称为外部排序,外部排序最常用的算法是多路归并排序,即将源文件分解为多个能够一次性注入到内存中的小文件,将比较结果在两两比较,依次,直到比较出最终结果。

我们平时说的排序都是指的内部排序。

3.内部排序分类

3.1选择排序

3.1.1直接选择排序

算法思想:

需要经过n-1次比较。

第一次比较:

程序将记录定位在第一个数据,拿第一个数据依次和后面每个数据进行比较,如果第一个数据大于后面的某个数据,交换他们……依次类推。

经过第一次比较,这些数据中的最小值就被选出,放在第一位。

第二次比较:

程序将记录定位在第二个数据,让第二个数据依次和后面的每个数据进行比较,如果第二个数据比后面的某个数据大,则交换它们,依次类推。

经过第二次比较,这些数据中第二小的数据就被选出,并且排在第二位。

按照此规则一共进行n-1次比较。

对应的java代码,此处一共两个类:

DataSource类(后面的排序数据的封装都是用的此类):

packagesuanfa;

/*

*定义一个数据封装包

**/

publicclassDataSourceimplementsComparable{

privateintdata;

privateStringflag;

publicintgetData(){

returndata;

}

publicvoidsetData(intdata){

this.data=data;

}

publicStringgetFlag(){

returnflag;

}

publicvoidsetFlag(Stringflag){

this.flag=flag;

}

publicDataSource(intdata,Stringflag){

this.data=data;

this.flag=flag;

}

publicStringtoString(){

returndata+flag;

}

@Override

publicintcompareTo(DataSourceo){

returnthis.data>o.data?

1:

(this.data==o.data?

0:

-1);

}

}

SelectSort类:

packagesuanfa;

importjava.util.Arrays;

publicclassSelectorSort{

publicstaticvoidselectSort(DataSource[]datas){

System.out.println("开始排序:

");

intarrayLength=datas.length;

for(inti=0;i

for(intj=i+1;j

if(datas[i].compareTo(datas[j])>0){

DataSourcetmp=datas[i];

datas[i]=datas[j];

datas[j]=tmp;

}

}

System.out.println(Arrays.toString(datas));

}

}

publicstaticvoidmain(String[]args){

DataSource[]datas={newDataSource(21,""),newDataSource(30,""),

newDataSource(49,""),newDataSource(30,"*"),

newDataSource(16,""),newDataSource(9,""),

newDataSource(27,"")};

System.out.println("排序之前:

\n"+Arrays.toString(datas));

selectSort(datas);

System.out.println("排序之后:

\n"+Arrays.toString(datas));

}

}

输出结果如下:

直接选择排序时不稳定,从两个30就可以看出。

优化:

由于直接排序算法的意图就是每一次找出其中的最小值,所以我们没必要后面的数只要比第一个数小就要进行交换,我们只需要找到每次后面的最小数就行,我们可以假定最小数为第一个,即将第一个数的索引赋值给一个变量,然后和后面的数进行比较,如果后面的数小于第一个数,就将后面数的索引赋给之前定义的变量。

比较完之后假如索引数仍未第一个数的索引,则说明最小数就是第一个,不用改变。

假如索引发生变化,则将后面的数与第一个数进行交换。

然后进行下一次的比较,我们可以将上面红色的代码修改为:

for(inti=0;i

intminIndex=i;

for(intj=i+1;j

if(datas[minIndex].compareTo(datas[j])>0){

minIndex=j;

}

}

if(minIndex!

=i){

DataSourcedata=datas[minIndex];

datas[minIndex]=datas[i];

datas[i]=data;

}

System.out.println(Arrays.toString(datas));

}

3.1.2堆排序

3.1.2.1概念

假如有n个数据元素的序列k0,k1,…,kn-1,当且仅当满足如下关系时,可以将这组数据称为小顶堆(小根堆)。

Ki<=K2i+1且Ki<=K2i+2(其中i=0,2,…,(n-1)/2)

若将上述表达式中的小于等于换为大于等于,则这组数据称为大顶堆(大根堆)。

假如将小顶堆或者大顶堆的数据元素排列为完全二叉树的话,对于小顶堆,树中所有节点的值都小于其左右节点的值,此树的根节点的值最小。

对于大顶堆则完全相反。

堆排序的关键是建堆。

3.1.2.2排序过程

Ø第一趟将索引0~n-1处的全部数据建立大顶堆或者小顶堆,就可以选择出这组数组中的最大值或者最小值,然后将最大值或者最小值与数组中的最后一个节点交换,这样最大值或者最小值就排在最后。

Ø第二趟将索引0~n-2处的全部数据建立大顶堆或者小顶堆,然后选择出第二大或者第二小的数据,然后将选择出的数据与数组中倒数第二个节点进行交换,这样第二大或者第二小的数据就排在倒数第二位。

Ø……

Ø第k趟将索引0~n-k处的全部数据建立大顶堆或者小顶堆,就可以选择出剩余数据中的最大值或者最小值,然后将大顶堆或者小顶堆的根节点与这组数据中的倒数第k个节点交换,使得这组数据的最大值或者最小值排在倒数第k位。

由于建堆的过程就是选取最大值或者最小值,因此堆排序的实质就是选择排序。

堆排序与直接选择排序的区别:

堆排序通过树形结构保存部分比较结果,可减少比较次数,从而提高效率。

而直接选择排序第一次需要进行n-1次比较,第二次需要进行n-2次比较,在n-2次比较中,有许多比较有可能在前面的n-1次比较中已经做过,但是由于前面的比较未能保留比较结果,所以后面的比较就进行了重复性的工作,从而使得效率降低。

3.1.2.3建堆过程

以建立大顶堆为例。

始终重复这一过程:

从最后一个非叶子节点开始,比较该节点和它的两个子节点的值,如果某个子节点的值大于父节点的值,把父节点和较大的子节点进行交换。

向前逐步调整直到根节点,即保证每个父节点的值都大于等于其左右两个子节点的值。

3.1.2.4源代码

packagesuanfa;

importjava.util.Arrays;

publicclassHeapSort

{

//交换data数组中索引i与j处的值

privatestaticvoidswap(DataSource[]data,inti,intj)

{

DataSourcetmp=data[i];

data[i]=data[j];

data[j]=tmp;

}

//对data数组从0到lastIndex建大顶堆

privatestaticvoidbuildMaxHeap(DataSource[]data,intlastIndex)

{

for(inti=(lastIndex-1)/2;i>=0;i--)

{

//保存当前正在判断的节点

intk=i;

//如果当前K节点的子节点存在

while(k*2+1<=lastIndex)

{

//k节点的左子节点的索引

intbiggerIndex=2*k+1;

//如果biggerIndex小于lastIndex,即biggerIndex+1

//代表的k节点的右子结点存在

if(biggerIndex

{

if(data[biggerIndex].compareTo(data[biggerIndex+1])<0)

{

//biggerIndex总是记录较大子节点的索引

biggerIndex++;

}

}

//如果K节点的值小于其较大子节点的值

if(data[k].compareTo(data[biggerIndex])<0)

{

//交换它们

swap(data,k,biggerIndex);

//将biggerIndex赋值给k,开始while循环的下一个循环

//重新保证k节点的值大于其左右两个子节点的值

k=biggerIndex;

}else

{

break;

}

}

}

}

publicstaticvoidheapSort(DataSource[]data)

{

System.out.println("开始排序");

intarrayLength=data.length;

for(inti=0;i

{

//建大顶堆

buildMaxHeap(data,arrayLength-1-i);

swap(data,0,arrayLength-1-i);

System.out.println(Arrays.toString(data));

}

}

publicstaticvoidmain(String[]args)

{

DataSource[]data={newDataSource(21,""),newDataSource(30,""),

newDataSource(49,""),newDataSource(30,"*"),

newDataSource(21,"*"),newDataSource(16,""),

newDataSource(9,"")};

System.out.println("排序之前:

\n"+Arrays.toString(data));

heapSort(data);

System.out.println("排序之后:

\n"+Arrays.toString(data));

}

}

排序结果:

根据结果可知,堆排序是不稳定的。

3.2交换排序

3.2.1冒泡排序

基本思想:

对于一组包含n个数据的一组记录,最坏的情况下,冒泡排序需要进行n-1趟比较。

第1趟:

依次比较0和1、1和2、2和3……n-2和n-1索引的元素,如果发现第一个元素大于后一个元素,交换它们。

经过第一趟,最大的元素排在后边。

后面重复上述过程。

3.2.1.1源代码

packagesuanfa;

importjava.util.Arrays;

publicclassBubbleSort

{

publicstaticvoidbubbleSort(DataSource[]data)

{

System.out.println("开始排序");

intarrayLength=data.length;

for(inti=0;i

{

booleanflag=false;

for(intj=0;j

{

if(data[j].compareTo(data[j+1])>0)

{

DataSourcetmp=data[j];

data[j]=data[j+1];

data[j+1]=tmp;

flag=true;

}

}

System.out.println(Arrays.toString(data));

//如果某趟没有发生交换,则表明已经处于有序状态

if(!

flag)

{

break;

}

}

}

publicstaticvoidmain(String[]args)

{

DataSource[]data={newDataSource(9,""),newDataSource(16,""),

newDataSource(21,"*"),newDataSource(23,""),

newDataSource(30,""),newDataSource(49,""),

newDataSource(21,""),newDataSource(30,"*")};

System.out.println("排序之前:

\n"+Arrays.toString(data));

bubbleSort(data);

System.out.println("排序之后:

\n"+Arrays.toString(data));

}

}

结果显示:

根据结果显示冒泡排序是稳定的。

3.2.2快速排序

基本思想:

从待排的数据序列中任取一个数据(如第一个数据)作为分界值,所有比它小的数值都放在左边,所有比它大的数值都放在右边。

经过这一趟下来,所有的数据分为两个序列,左边序列的值比分界值小,右边序列的值比分界值大。

然后再对左右两个子序列进行递归,对两个子序列重新选择中心元素并依此规则调整,直到每个子表的元素只剩一个,排序完成。

关键:

Ø选取分界值

Ø将所有比分界值小的元素都放在左边

Ø将所有比分界值大的元素都放在右边

实现关键步骤中的第2、3步的思路:

Ø定义一个i变量,i变量从左边第一个索引开始,找大于分界值的元素的索引,并用i来记录它。

Ø定义一个j变量,j变量从右边第一个索引开始,找小于分界值的元素索引,并用j来记录它。

Ø如果i

Ø重复上述过程,直到i>=j,可以判断j左边的元素都小于分界值,j右边的元素都大于分界值,最后将分界值和j索引处的元素交换即可。

3.2.2.1源代码

packagesuanfa;

importjava.util.Arrays;

publicclassQuickSort

{

privatestaticvoidswap(DataSource[]data,inti,intj)

{

DataSourcetmp=data[i];

data[i]=data[j];

data[j]=tmp;

}

//对data数组中从start~end索引范围的子序列进行处理

//使之满足所有小于分界值的放在左边,所有大于分界值的放在右边

privatestaticvoidsubSort(DataSource[]data,intstart,intend)

{

//需要排序

if(start

{

//以第一个元素作为分界值

DataSourcebase=data[start];

inti=start;

intj=end+1;

while(true)

{

//找到小于分界值的元素的索引,或者i已经到了end处

while(i=0);

//找到大于分界值的元素的索引,或者j已经到了start处

while(j>start&&data[--j].compareTo(base)<=0);if(i

{

swap(data,i,j);

}else

{

break;

}

}

swap(data,start,j);

//递归左子序列

subSort(data,start,j-1);

//递归右子序列

subSort(data,j+1,end);

}

}

privatestaticvoidquickSort(DataSource[]data)

{

subSort(data,0,data.length-1);

}

publicstaticvoidmain(String[]args)

{

DataSource[]data={newDataSource(9,""),newDataSource(-16,""),

newDataSource(21,"*"),newDataSource(23,""),

newDataSource(-30,""),newDataSource(-49,""),

newDataSource(21,""),newDataSource(30,"*"),

newDataSource(13,"*")};

System.out.println("排序之前:

\n"+Arrays.toString(data));

quickSort(data);

System.out.println("排序之后:

\n"+Arrays.toString(data));

}

}

结果显示:

3.3插入排序

3.3.1直接插入排序

基本思想:

依次将待定排序的数据元素按其关键字的大小插入前面的有序序列。

第一趟插入:

将第二个元素插入前面的有序子序列中----此时前面只有一个元素,必须有序。

第二趟插入:

将第三个元素插入前面的有序子序列中-----前面2个元素是有序的。

…………….

第n-1趟插入:

将第n个元素插入到前面的有序子序列中------前面n-2个元素师有序的。

3.3.1.1源代码

packagesuanfa;

importjava.util.Arrays;

publicclassInsertSort

{

privatestaticvoidinsertSort(DataSource[]data)

{

System.out.println("开始排序");

intarrayLength=data.length;

for(inti=1;i

{

//当整体后移的时候,保证data[i]处的数据不会丢失

DataSourcetmp=data[i];

//i索引处的值已经比前面的所有值都大,表明已经有序,无需插入

//i-1索引前的数据已经是有序的,i-1索引处元素的值是最大值

if(data[i].compareTo(data[i-1])<0)

{

//整体后移一格

intj=i-1;

for(;j>=0&&data[j].compareTo(tmp)>0;j--)

{

data[j+1]=data[j];

}

data[j+1]=tmp;

}

System.out.println(Arrays.toString(data));

}

}

publicstaticvoidmain(String[]args)

{

DataSource[]data={newDataSource(9,""),newDataSource(-16,""),

newDataSource(21,"*"),newDataSource(23,""),

newDataSource(-30,""),newDataSource(-49,""),

newDataSource(21,""),newDataSource(30,"*"),

newDataSource(30,"")};

System.out.println("排序之前:

\n"+Arrays.toString(data));

insertSort(data);

System.out.println("排序之后:

\n"

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 教学研究 > 教学反思汇报

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1