




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
\o"JavaEE知识库"Java当中有以下几种常见排序算法:插入排序(直接插入排序、链表插入排序、分段/二分/折半插入排序、希尔排序/缩小增量排序)、冒泡排序、快速排序、简单选择排序、归并排序、二叉树排序、基数排序等。(1)复杂度比较表1几种常见排序算法的复杂度算法名称平均情况最好情况最坏情况辅助空间直接插入排序O(n^2)O(n)O(n^2)O(1)希尔排序O(nlog2n)~
o(n^2)O(n^1.3)O(n^2)O(1)冒泡排序O(n^2)O(n)O(n^2)O(1)快速排序O(nlog2n)O(nlog2n)O(n^2)O(n)简单选择排序O(n^2)O(n^2)O(n^2)O(1)堆排序O(nlog2n)O(nlog2n)O(nlog2n)O(1)归并排序O(nlog2n)O(nlog2n)O(nlog2n)O(n)
基数排序O(n)O(n)O(n)O(1)
什么是排序算法的稳定性?
假设在待排序的记录中,有若干个相同的元素,如果排序后它们的相对位置并没有发生变化,则说明该排序是稳定的。
(2)稳定性比较插入排序、冒泡排序、二叉树排序、二路归并排序及其他线形排序是稳定的,选择排序、希尔排序、快速排序、堆排序是不稳定的。(3)其他方面比较插入、冒泡排序的速度较慢,但参加排序的序列局部或整体有序时,这种排序能达到较快的速度。反而在这种情况下,快速排序反而慢了。当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序。若待排序的记录的关键字在一个明显有限范围内时,且空间允许时用桶排序。当n较大时,关键字元素比较随机,对稳定性没要求宜用快速排序。当n较大时,关键字元素可能出现本身是有序的,对稳定性有要求时,空间允许的情况下。宜用归并排序。当n较大时,关键字元素可能出现本身是有序的,对稳定性没有要求时宜用堆排序。=============================================================================
相关知识介绍(所有定义只为帮助读者理解相关概念,并非严格定义):
1、稳定排序和非稳定排序简单地说就是所有相等的数经过某种排序方法后,仍能保持它们在排序之前的相对次序,我们就
说这种排序方法是稳定的。反之,就是非稳定的。
比如:一组数排序前是a1,a2,a3,a4,a5,其中a2=a4,经过某种排序后为a1,a2,a4,a3,a5,
则我们说这种排序是稳定的,因为a2排序前在a4的前面,排序后它还是在a4的前面。假如变成a1,a4,
a2,a3,a5就不是稳定的了。2、内排序和外排序在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序;
在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序。3、算法的时间复杂度和空间复杂度所谓算法的时间复杂度,是指执行算法所需要的计算工作量。
一个算法的空间复杂度,一般是指执行这个算法所需要的内存空间。
=============================================================================一、插入排序包括:直接插入排序,二分插入排序(又称折半插入排序),链表插入排序,希尔排序(又称缩小增量排序)。属于稳定排序的一种(通俗地讲,就是两个相等的数不会交换位置)。(a)直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的纪录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的纪录插入完为止,得到一个新的有序序列。已知一组升序排列数据a[1]、a[2]、……a[n],一组无序数据b[1]、b[2]、……b[m],需将二者合并成一个升序数列。首先比较b[1]与a[1]的值,若b[1]大于a[1],则跳过,比较b[1]与a[2]的值,若b[1]仍然大于a[2],则继续跳过,直到b[1]小于a数组中某一数据a[x],则将a[x]~a[n]分别向后移动一位,将b[1]插入到原来a[x]的位置这就完成了b[1]的插入。b[2]~b[m]用相同方法插入。(若无数组a,可将b[1]当作n=1的数组a)优点:稳定,快;缺点:比较次数不一定,比较次数越少,插入点后的数据移动越多,特别是当数据总量庞大的时候,但用链表可以解决这个问题。(b)分段插入排序已知一组升序排列数据a[1]、a[2]、……a[n],一组无序数据b[1]、b[2]、……b[m],需将二者合并成一个升序数列。先将数组a分成x等份(x<<n),每等份有n/x个数据。将每一段的第一个数据先储存在数组c中:c[1]、c[2]、……c[x]。运用插入排序处理数组b中的数据。插入时b先与c比较,确定了b在a中的哪一段之后,再到a中相应的段中插入b。随着数据的插入,a中每一段的长度会有变化,所以在每次插入后,都要检测一下每段数据的量的标准差s,当其大于某一值时,将a重新分段。在数据量特别巨大时,可在a中的每一段中分子段,b先和主段的首数据比较,再和子段的首数据比较,可提高速度。优点:快,比较次数少;缺点:不适用于较少数据的排序,s的临界值无法确切获知,只能凭经验取。(c)希尔排序/缩小增量排序由希尔在1959年提出,又称希尔排序。已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。发现当n不大时,插入排序的效果很好。首先取一增量d(d<n),将a[1]、a[1+d]、a[1+2d]……列为第一组,a[2]、a[2+d]、a[2+2d]……列为第二组……,a[d]、a[2d]、a[3d]……列为最后一组依此类推,在各组内用插入排序,然后取d'<d,重复上述操作,直到d=1。优点:快,数据移动少;缺点:不稳定,d的取值是多少,应取多少个不同的值,都无法确切知道,只能凭经验来取。
三、冒泡排序已知一组无序数据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[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。一趟快速排序的算法是:1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;5)重复第3、4步,直到i=j;
(3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i,
j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。快速排序是冒泡排序的改进版,是目前已知的最快的排序方法。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。即使a[1]~a[k-1]中的每一个数据<a[x],a[k+1]~a[n]中的每一个数据>a[x],然后采用分治的策略分别对a[1]~a[k-1]和a[k+1]~a[n]两组数据进行快速排序。优点:极快,数据移动少;缺点:不稳定。编码实现如下:
packagecom.quick;
publicclassquick{
publicvoidquick_sort(int[]arrays,intlenght){
if(null==arrays||lenght<1){
System.out.println("inputerror!");
return;
}
_quick_sort(arrays,0,lenght-1);
}
publicvoid_quick_sort(int[]arrays,intstart,intend){
if(start>=end){
return;
}
inti=start;
intj=end;
intvalue=arrays[i];
booleanflag=true;
while(i!=j){
if(flag){
if(value>arrays[j]){
swap(arrays,i,j);
flag=false;
}else{
j--;
}
}else{
if(value<arrays[i]){
swap(arrays,i,j);
flag=true;
}else{
i++;
}
}
}
snp(arrays);
_quick_sort(arrays,start,j-1);
_quick_sort(arrays,i+1,end);
}
publicvoidsnp(int[]arrays){
for(inti=0;i<arrays.length;i++){
System.out.print(arrays[i]+"");
}
System.out.println();
}
privatevoidswap(int[]arrays,inti,intj){
inttemp;
temp=arrays[i];
arrays[i]=arrays[j];
arrays[j]=temp;
}
publicstaticvoidmain(Stringargs[]){
quickq=newquick();
int[]a={49,38,65,12,45,5};
q.quick_sort(a,6);
}
}=============================================================================Java123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127classQuick{publicvoidsort(intarr[],intlow,inthigh){intl=low;inth=high;intpovit=arr[low];
while(l<h){while(l<h&&arr[h]>=povit)h--;if(l<h){inttemp=arr[h];arr[h]=arr[l];arr[l]=temp;l++;}
while(l<h&&arr[l]<=povit)l++;
if(l<h){inttemp=arr[h];arr[h]=arr[l];arr[l]=temp;h--;}}print(arr);System.out.print("l="+(l+1)+"h="+(h+1)+"povit="+povit+"\n");if(l>low)sort(arr,low,l-1);if(h<high)sort(arr,l+1,high);}}
/*//////////////////////////方式二////////////////////////////////*/更高效点的代码:public<TextendsComparable<?superT>>T[]quickSort(T[]targetArr,intstart,intend){inti=start+1,j=end;Tkey=targetArr[start];SortUtil<T>sUtil=newSortUtil<T>();
if(start>=end)return(targetArr);
/*从i++和j--两个方向搜索不满足条件的值并交换**条件为:i++方向小于key,j--方向大于key*/while(true){while(targetArr[j].compareTo(key)>0)j--;while(targetArr[i].compareTo(key)<0&&i<j)i++;if(i>=j)break;sUtil.swap(targetArr,i,j);if(targetArr[i]==key){j--;}else{i++;}}
/*关键数据放到‘中间’*/sUtil.swap(targetArr,start,j);
if(start<i-1){this.quickSort(targetArr,start,i-1);}if(j+1<end){this.quickSort(targetArr,j+1,end);}
returntargetArr;}
/*//////////////方式三:减少交换次数,提高效率/////////////////////*/private<TextendsComparable<?superT>>voidquickSort(T[]targetArr,intstart,intend){inti=start,j=end;Tkey=targetArr[start];
while(i<j){/*按j--方向遍历目标数组,直到比key小的值为止*/while(j>i&&targetArr[j].compareTo(key)>=0){j--;}if(i<j){/*targetArr[i]已经保存在key中,可将后面的数填入*/targetArr[i]=targetArr[j];i++;}/*按i++方向遍历目标数组,直到比key大的值为止*/while(i<j&&targetArr[i].compareTo(key)<=0)/*此处一定要小于等于零,假设数组之内有一亿个1,0交替出现的话,而key的值又恰巧是1的话,那么这个小于等于的作用就会使下面的if语句少执行一亿次。*/{i++;}if(i<j){/*targetArr[j]已保存在targetArr[i]中,可将前面的值填入*/targetArr[j]=targetArr[i];j--;}}/*此时i==j*/targetArr[i]=key;
/*递归调用,把key前面的完成排序*/this.quickSort(targetArr,start,i-1);
/*递归调用,把key后面的完成排序*/this.quickSort(targetArr,j+1,end);
}=============================================================================五、选择排序算法思想简单描述:在要排序的一组数中,选出最小的一个数与第一个位置的数交换;
然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环
到倒数第二个数和最后一个数比较为止。选择排序是不稳定的。算法复杂度O(n^2)优点:稳定,比较次数与冒泡排序一样,数据移动次数比冒泡排序少;缺点:相对之下还是慢。=====================================================
*/
voidselect_sort(int*x,intn)
{
inti,j,min,t;for(i=0;i<n-1;i++)/*要选择的次数:0~n-2共n-1次*/
{
min=i;/*假设当前下标为i的数最小,比较后再调整*/
for(j=i+1;j<n;j++)/*循环找出最小的数的下标是哪个*/
{
if(*(x+j)<*(x+min))
{
min=j;/*如果后面的数比前面的小,则记下它的下标*/
}
}
if(min!=i)/*如果min在循环中改变了,就需要交换数据*/
{
t=*(x+i);
*(x+i)=*(x+min);
*(x+min)=t;
}
}
}
/*
================================================
六、堆排序堆积排序(Heapsort)是指利用堆积树(堆)这种资料结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。堆排序是不稳定的排序方法,辅助空间为O(1),最坏时间复杂度为O(nlog2n)
,堆排序的堆序的平均性能较接近于最坏性能。
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。(1)用大根堆排序的基本思想①先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区②再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。……直到无序区只有一个元素为止。(2)大根堆排序算法的基本操作:
①初始化操作:将R[1..n]构造为初始堆;②每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。注意:
①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。代码实现:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?public
class
HeapSortTest
{
public
static
void
main(String[]
args)
{
int[]
data5
=
new
int[]
{
5,
3,
6,
2,
1,
9,
4,
8,
7
};
print(data5);
heapSort(data5);
System.out.println("排序后的数组:");
print(data5);
}
public
static
void
swap(int[]
data,
int
i,
int
j)
{
if
(i
==
j)
{
return;
}
data[i]
=
data[i]
+
data[j];
data[j]
=
data[i]
-
data[j];
data[i]
=
data[i]
-
data[j];
}
public
static
void
heapSort(int[]
data)
{
for
(int
i
=
0;
i
<
data.length;
i++)
{
createMaxdHeap(data,
data.length
-
1
-
i);
swap(data,
0,
data.length
-
1
-
i);
print(data);
}
}
public
static
void
createMaxdHeap(int[]
data,
int
lastIndex)
{
for
(int
i
=
(lastIndex
-
1)
/
2;
i
>=
0;
i--)
{
//
保存当前正在判断的节点
int
k
=
i;
//
若当前节点的子节点存在
while
(2
*
k
+
1
<=
lastIndex)
{
//
biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点
int
biggerIndex
=
2
*
k
+
1;
if
(biggerIndex
<
lastIndex)
{
//
若右子节点存在,否则此时biggerIndex应该等于
lastIndex
if
(data[biggerIndex]
<
data[biggerIndex
+
1])
{
//
若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的值
biggerIndex++;
}
}
if
(data[k]
<
data[biggerIndex])
{
//
若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k
swap(data,
k,
biggerIndex);
k
=
biggerIndex;
}
else
{
break;
}
}
}
}
public
static
void
print(int[]
data)
{
for
(int
i
=
0;
i
<
data.length;
i++)
{
System.out.print(data[i]
+
"\t");
}
System.out.println();
}
}
运行结果:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?5
3
6
2
1
9
4
8
7
3
8
6
7
1
5
4
2
9
2
7
6
3
1
5
4
8
9
4
3
6
2
1
5
7
8
9
4
3
5
2
1
6
7
8
9
1
3
4
2
5
6
7
8
9
2
3
1
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
排序后的数组:
1
2
3
4
5
6
7
8
9
整个排序过程图解:(待有时间再补充...)
七、归并排序归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(DivideandConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。归并排序算法稳定,数组需要O(n)的额外空间,链表需要O(log(n))的额外空间,时间复杂度为O(nlog(n)),算法不是自适应的,不需要对数据的随机读取。工作原理:1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列2、设定两个指针,最初位置分别为两个已经排序序列的起始位置3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置4、重复步骤3直到某一指针达到序列尾5、将另一序列剩下的所有元素直接复制到合并序列尾代码实现:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?public
class
MergeSortTest
{
public
static
void
main(String[]
args)
{
int[]
data
=
new
int[]
{
5,
3,
6,
2,
1,
9,
4,
8,
7
};
print(data);
mergeSort(data);
System.out.println("排序后的数组:");
print(data);
}
public
static
void
mergeSort(int[]
data)
{
sort(data,
0,
data.length
-
1);
}
public
static
void
sort(int[]
data,
int
left,
int
right)
{
if
(left
>=
right)
return;
//
找出中间索引
int
center
=
(left
+
right)
/
2;
//
对左边数组进行递归
sort(data,
left,
center);
//
对右边数组进行递归
sort(data,
center
+
1,
right);
//
合并
merge(data,
left,
center,
right);
print(data);
}
/**
*
将两个数组进行归并,归并前面2个数组已有序,归并后依然有序
*
*
@param
data
*
数组对象
*
@param
left
*
左数组的第一个元素的索引
*
@param
center
*
左数组的最后一个元素的索引,center+1是右数组第一个元素的索引
*
@param
right
*
右数组最后一个元素的索引
*/
public
static
void
merge(int[]
data,
int
left,
int
center,
int
right)
{
//
临时数组
int[]
tmpArr
=
new
int[data.length];
//
右数组第一个元素索引
int
mid
=
center
+
1;
//
third
记录临时数组的索引
int
third
=
left;
//
缓存左数组第一个元素的索引
int
tmp
=
left;
while
(left
<=
center
&&
mid
<=
right)
{
//
从两个数组中取出最小的放入临时数组
if
(data[lef
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 大学生消费者冲动性购买意愿影响因素研究
- 摩擦作用下钎料-Cu柱界面反应及近界面钎料的晶体学特征
- 2025-2030年文化服装产品企业制定与实施新质生产力战略研究报告
- 2025-2030年可调节高度台球桌行业跨境出海战略研究报告
- 2025-2030年文具租赁与回收服务企业制定与实施新质生产力战略研究报告
- 磁场辅助pH-shifting技术对冷冻猪肉肌原纤维蛋白品质的影响规律研究
- 法律咨询行业法律顾问服务合同协议
- 2025-2030年户外探险寻宝游戏行业深度调研及发展战略咨询报告
- 初中物理单元作业设计教学研究
- 递减、递增负荷抗阻训练对男性大学生下肢肌力的影响研究
- 高中主题班会 悟哪吒精神做英雄少年-下学期开学第一课主题班会课件-高中主题班会课件
- 2024年青岛港湾职业技术学院高职单招语文历年参考题库含答案解析
- 广西壮族自治区公路发展中心2025年面向社会公开招聘657名工作人员高频重点提升(共500题)附带答案详解
- 大学转专业高等数学试卷
- DBJ51-T 198-2022 四川省既有民用建筑结构安全隐患排查技术标准
- 公司厂区保洁培训
- 江苏省招标中心有限公司招聘笔试冲刺题2025
- (高清版)JTGT 3360-01-2018 公路桥梁抗风设计规范
- (高清版)TDT 1042-2013 土地整治工程施工监理规范
- 装饰施工进度计划网络图及横道图
- 实木电脑桌书桌安装图
评论
0/150
提交评论