计数基数排序实验报告.docx

上传人:b****2 文档编号:2622598 上传时间:2023-05-04 格式:DOCX 页数:15 大小:153.58KB
下载 相关 举报
计数基数排序实验报告.docx_第1页
第1页 / 共15页
计数基数排序实验报告.docx_第2页
第2页 / 共15页
计数基数排序实验报告.docx_第3页
第3页 / 共15页
计数基数排序实验报告.docx_第4页
第4页 / 共15页
计数基数排序实验报告.docx_第5页
第5页 / 共15页
计数基数排序实验报告.docx_第6页
第6页 / 共15页
计数基数排序实验报告.docx_第7页
第7页 / 共15页
计数基数排序实验报告.docx_第8页
第8页 / 共15页
计数基数排序实验报告.docx_第9页
第9页 / 共15页
计数基数排序实验报告.docx_第10页
第10页 / 共15页
计数基数排序实验报告.docx_第11页
第11页 / 共15页
计数基数排序实验报告.docx_第12页
第12页 / 共15页
计数基数排序实验报告.docx_第13页
第13页 / 共15页
计数基数排序实验报告.docx_第14页
第14页 / 共15页
计数基数排序实验报告.docx_第15页
第15页 / 共15页
亲,该文档总共15页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

计数基数排序实验报告.docx

《计数基数排序实验报告.docx》由会员分享,可在线阅读,更多相关《计数基数排序实验报告.docx(15页珍藏版)》请在冰点文库上搜索。

计数基数排序实验报告.docx

计数基数排序实验报告

实验二计数基数排序

1.实验环境

本次算法实验选用java语言实现,环境:

JDK11.8;编译器:

eclipse

2.实验目的

通过计数排序和基数排序问题,更进一步了解排序思想和程序设计的思想和技巧。

3.计数排序

3.1设计思路

对于特定元素x来说,如果我们知道给定序列里比它小的元素的个数,则x的位置就已经确定。

如:

若序列比x小的元素有m个,则x在输出数组里面所占的位置就是m+1。

这就是计数排序:

对于每一个元素,我们计数比它小的元素个数,然后将该元素放入合适的位置。

给定一个输入数组:

A[1..n],这里A[j]∈{1,2,3,…,k},即每个元素的取值不超过k。

给定一个输出数组:

B[1..n],用于存放排好序的序列。

给定一个计数数组:

C[1..k],用于计数。

伪代码如下:

1.Fori<--1tokDo:

//将计数数组清零

C[i]<--0

2.Forj<--1tonDo:

//计数取值为A[j]的元素个数

C[A[j]]<--C[A[j]]+1

3.Fori<--2tokDo:

//计数取值为小于等于i的元素的个数

C[i]<--C[i]+C[i-1]]

4.Forj<--ndownto1Do:

B[C[A[j]]]<--A[j]//元素A[j]在输出数组里所处的位置为B[C[A[j]]]

C[A[J]]<--C[A[j]]–1//剩下的比取值小于等于A[j]的元素个数减1

3.2过程

例如我们需要对下面这个数组里的元素进行计数排序

A

6

1

4

5

8

3

4

第一行循环,计数数组C初始化为0:

(8个元素)

C

0

0

0

0

0

0

0

0

第二行循环后,计数C的元素变为:

C

1

0

1

2

1

1

0

1

第三行循环后,计数C变成:

C

1

1

2

4

5

6

6

7

第四行循环将每个元素放入它们相应的位置:

A

6

1

4

5

8

3

4

B

4

C

1

1

2

3

5

6

6

7

j=7:

A

6

1

4

5

8

3

4

B

3

4

C

1

1

1

3

5

6

6

7

j=6:

A

6

1

4

5

8

3

4

B

3

4

8

C

1

1

1

3

5

6

6

6

j=5:

A

6

1

4

5

8

3

4

B

3

4

5

8

C

1

1

1

3

4

6

6

6

j=4:

A

6

1

4

5

8

3

4

B

3

4

4

5

8

C

1

1

1

2

4

6

6

6

j=3:

A

6

1

4

5

8

3

4

B

1

3

4

4

5

8

C

0

1

1

2

4

6

6

6

j=2:

A

6

1

4

5

8

3

4

B

1

3

4

4

5

6

8

C

1

1

1

2

4

5

6

6

j=1:

至此,整个排序完成,B数组里面就是已经排好的序列:

1,3,4,4,5,6,8

3.3.实现源代码

packagecountsort;

publicclassCountSort{

privatestaticint[]countSort(int[]A,intk)

{

int[]C=newint[k+1];//构造C数组

intlength=A.length;//获取A数组大小用于构造B数组

int[]B=newint[length];//构造B数组

//第一个循环

for(inti=1;i<=k;i++){

C[i]=0;//将C初始化为0

}

//第二个循环

for(intj=0;j

{

C[A[j]]+=1;//统计A中各元素个数,存入C数组

}

//第三个循环

for(inti=1;i

{

C[i]=C[i]+C[i-1];

}

//第四个循环

for(inti=length-1;i>=0;i--)//遍历A数组,构造B数组

{

B[C[A[i]]-1]=A[i];//将A中该元素放到排序后数组B中指定的位置

C[A[i]]--;//将C中该元素-1,方便存放下一个同样大小的元素

}

returnB;//将排序好的数组返回,完成排序

}

publicstaticintgetMax(int[]arr){

intmax=arr[0];

for(inti=1;i

if(arr[i]>max){

max=arr[i];

}

}

returnmax;

}

publicstaticvoidmain(String[]args)

{

int[]A=newint[]{6,1,4,5,8,4,3};

intk=getMax(A);

int[]B=countSort(A,k);

for(inti=0;i

{

System.out.print(B[i]+"");

}

}

}

3.4断点调试及代码分析

在程序入口main方法里首先定义了需要排序的数组,然后编写了一个程序计算数组中的最大值,用于构造计数数组C:

然后调用计数排序的方法

参数的定义:

这里C的长度定义为k+1是为了方便从1开始计数

第一个循环,将C数组索引为1到k的值初始化为0:

第二个循环:

第三个循环:

第四个循环,因为数组为是从索引0开始的,为C是从索引1开始的,因此这里有一个减1操作:

然后返回数组B:

并在main方法中输出B数组:

3.5效率分析

计数排序一共只有4个循环,第1个循环需要执行k次,第2个循环一共执行n次,第3个循环执行k次,第4个循环执行n次。

因此,计数排序的时间复杂性为Θ(n+k),如果k=Ο(n),则计数排序的时间复杂性为Θ(n)。

但是此时的前提为:

k的数量级不高于n的数量级。

在计数排序算法里,计数数组C的大小为输入序列里最大元素的取值。

输入元素的取值范围越大,则计数数组C的空间需求也越大。

如果输入数组的元素取值很少,则数组C的大部分空间都会浪费。

如果k>>n,则计数排序就不再是线性的了,如k=Ο(n2),则Θ(n+k)=Θ(n2)

3.6实验结果

当数组源定义为:

时,得到的结果为

更换数据测试:

实验完成

4.基数排序

4.1设计思路

当输入序列里的元素取值很大的时候,计数排序算法在效率和可行性上都将崩溃,而基数排序却可以应付数值很大的情况。

该中算法在按照一个位数一个位数的进行排序,而对每个位数的排序则使用了某种稳定的排序。

因为越是后排的数位,对结果次序的影响越大,所以要先排最低有效位后排最高有效位。

4.2过程

下面是一个比较复杂的排序例子,第一次按个位数排序,第二次按十位数排序,第三次按百位数排序,第四次按千位数排序:

2323

3420

3420

8139

1338

5456

2323

2323

2323

2323

6657

4934

4934

1338

3420

8139

5495

1338

3420

4934

5495

5456

8139

5456

5456

1338

6657

5456

5495

5495

3420

1338

6657

6657

6657

4934

8139

5495

4934

8139

其中对每个位数的排序使用前面的计数排序算法。

4.3.实现源代码

packageradixsort;

publicclassRadixSort{

publicstaticint[]radixSort(int[]A,intdigit)

{

//低到高位

for(intk=1;k<=digit;k++)

{

int[]B=newint[A.length];//保存当前位的排序结果

int[]C=newint[10];//计数数组C

//计数排序算法的第一个循环

for(inti=0;i

C[i]=0;//将还数组清零

}

//计数排序算法的第二个循环

for(inti=0;i

{

//分离当前位

inttmpSplitDigit=A[i]/(int)Math.pow(10,k-1)-(A[i]/(int)Math.pow(10,k))*10;

//此时c保存的是当前位上的值的个数

C[tmpSplitDigit]+=1;

}

//计数排序算法的第三个循环

for(intm=1;m<10;m++)

{

C[m]+=C[m-1];

}

//计数排序算发的第四个循环

for(intn=A.length-1;n>=0;n--)

{

inttmpSplitDigit=A[n]/(int)Math.pow(10,k-1)-(A[n]/(int)Math.pow(10,k))*10;

B[C[tmpSplitDigit]-1]=A[n];

C[tmpSplitDigit]-=1;

}

//将当前排序值拷贝给A数组,进行下一位排序

for(intp=0;p

{

A[p]=B[p];

}

}

//返回最后结果

returnA;

}

publicstaticvoidmain(String[]args){

int[]ary=newint[]{332,653,632,755,433,722,48};

int[]res=radixSort(ary,3);

for(intvr=0;vr

System.out.println(res[vr]);

}

}

}

4.4断点调试及代码分析

在main方法中定义了需要排序的数组源

然后调用radixSort()方法,

参数A表示数组源,digit表示该数组最高有几位

第一层循环迭代位数

然后里面的前四个循环就是对当前位的数字进行计数排序算法,其中第二个循环里的:

tmpSplitDigit参数就是分离出来的当前位上的数字,将它写入计数数组C

第四个循环里的tmpSplitDigit在这里就相当于前面计数排序算法里的A数组

循环完一次后,就完成了对个位数的排序,然后再依次十位…直至到最高位排序完毕,算大就完成了实现。

4.5效率分析

基数排序的总时间成本是Θ(bn/lgn),此处b为二进制位数,n为数的个数。

4.6实验结果

定义数组源为

显而易见该数组的最高位为3位,所以调用radixSort():

输出结果:

得到:

更改数据源和radixSort()的digit参数测试,得到

也可以编写代码计算digit参数:

getDigit()方法:

privatestaticintgetDigit(int[]ary){

intvalue=getMax(ary);

intcount=0;

while(value/10>0){

count++;

value=value/10;

}

count++;//首位也要加进去

returncount;

}

方法首先调用getMax()方法得到该数组的最大值,再计算这个最大值的位数即为该数组的最大位数。

getMax()方法:

publicstaticintgetMax(int[]arr){

intmax=arr[0];

for(inti=1;i

if(arr[i]>max){

max=arr[i];

}

}

returnmax;

}

5.实验总结

计数排序算法的实现相较于基数排序算法简单一些,主要是思想上的理解,实现起来并不算太难;基数排序算法的难点在于分离位数,将分离出来的位数的个数作为计数数组的取值在对它进行计数排序算法。

基数排序算法的核心在于从低位向高位进行排序,因为如果要从高位排序,那么次高位的排序会影响高位已经排好的大小关系.在数学中,数位越高,数位值对数的大小的影响就越大.从低位开始排序,就是对这种影响的排序.数位按照影响力从低到高的顺序排序,数位影响力相同则比较数位值。

在对每一位数进行稳定排序的时候,选择时候计数排序算法,计数排序算法适用于数组源中的元素值小,在这里,每一位数的取值都为[0..9],因此选择该算法比较客观。

稳定排序的意思是指,待排序相同元素之间的相对前后关系,在各次排序中不会改变.比如实例中具有十位数字5的两个数字58和356,在十位排序之前356在58之前,在十位排序之后,356依然在58之前。

稳定排序能保证,上一次的排序成果被保留,十位数的排序过程能保留个位数的排序成果,百位数的排序过程能保留十位数的排序成果。

通过这一次的实验,不仅仅是对这两种排序算法的学习实现,更加深了我对算法思想的理解,拓宽了编程的思维,对以后的编程学习有了更大的帮助。

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

当前位置:首页 > 考试认证 > 从业资格考试

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2