1.快速排序和希尔排序不是稳定的排序方式,冒泡排序和插入排序是稳定的排序方式;
2.各种排序算法的分析和说明?
2.1-----冒泡排序
冒泡排序就是把小的元素往前调(或者把大的元素往后调)。注意是相邻的两个元素进行比较,而且是否需要交换也发生在这两个元素之间。
所以,如果两个元素相等,我想你是不会再无聊地把它们俩再交换一下。
如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个元素相邻起来,最终也不会交换它俩的位置,所以相同元素经过排序后顺序并没有改变。
所以冒泡排序是一种稳定排序算法。
public static int[] bubbleSort(int[] arr)
{
for(int i=0;i<arr.length-1;i++)
{
for(int j=i+1;j<arr.length;j++)
{
if(arr[i]>arr[j])
{
int temp;
temp=arr[j];
arr[j]=arr[i];
arr[i]=temp;
}
}
}
return arr;
}
2.2--------快速排序 快速排序有两个方向,左边的i下标一直往右走(当条件a[i] <= a[center_index]时),其中center_index是中枢元素的数组下标,一般取为数组第0个元素。
而右边的j下标一直往左走(当a[j] > a[center_index]时)。
如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。交换a[j]和a[center_index],完成一趟快速排序。
在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11
现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱。
所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。
publicstaticvoidquickSort(inta[],intstart,intend)
{inti,j;
i=start;
j=end;
if((a==null)||(a.length==0))
return;
while(i<j){
while(i<j&&a[i]<=a[j]){//以数组start下标的数据为key,右侧扫描
j--;
}
if(i<j){//右侧扫描,找出第一个比key小的,交换位置
inttemp=a[i];
a[i]=a[j];
a[j]=temp;
}
while(i<j&&a[i]<a[j]){//左侧扫描(此时a[j]中存储着key值)
i++;
}
if(i<j){//找出第一个比key大的,交换位置
inttemp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
if(i-start>1){
//递归调用,把key前面的完成排序
quickSort(a,start,i-1);
}
if(end-i>1){
quickSort(a,i+1,end);//递归调用,把key后面的完成排序
}
}
2.3----------插入排序
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,也就是第一个元素(默认它有序)。
比较是从有序序列的末尾开始,也就是把待插入的元素和已经有序的最大者开始比起,如果比它大则直接 插入在其后面。
否则一直往前找直到找到它该插入的位置。如果遇见一个与插入元素相等的,那么把待插入的元素放在相等元素的后面。
所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序仍是排好序后的顺序,所以插入排序是稳定的。
---------------------------直接插入排序
public
class
MainTest {
public
static
void
main(String[] args) {
int
[] a = {
46
,
58
,
15
,
45
,
90
,
18
,
10
,
62
};
int
n = a.length;
int
i, j;
for
(i =
0
; i < n; i++) {
int
temp = a[i];
for
(j = i; j >
0
&& temp < a[j-
1
]; j--) {
a[j] = a[j -
1
];
}
a[j] = temp;
}
for
(i=
0
;i<n;i++){
System.out.print(a[i]+
"\t"
);
}
}
-----------------折半插入排序
在将一个新元素插入已排好序的数组的过程中,寻找插入点时,将待插入区域的首元素设置为a[low],末元素设置为a[high],则轮比较时将待插入元素与a[m],其中m=(low+high)/2相比较,如果比参考元素大,则选择a[low]到a[m-1]为新的插入区域(即high=m-1),否则选择a[m+1]到a[high]为新的插入区域(即low=m+1),如此直至low<=high不成立,即将此位置之后所有元素后移一位,并将新元素插入a[high+1]。[1]
折半插入排序算法是一种稳定的排序算法,比直接插入算法明显减少了关键字之间比较的次数,因此速度比直接插入排序算法快,但记录移动的次数没有变,所以折半插入排序算法的时间复杂度仍然为O(n^2),与直接插入排序算法相同。附加空间O(1)。[1]
2.4 希尔排序
该方法实质上是一种分组插入方法
由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。
package
com.sort;
//不稳定
public
class
希尔排序 {
public
static
void
main(String[] args) {
int
[] a={
49
,
38
,
65
,
97
,
76
,
13
,
27
,
49
,
78
,
34
,
12
,
64
,
1
};
System.out.println(
"排序之前:"
);
for
(
int
i =
0
; i < a.length; i++) {
System.out.print(a[i]+
" "
);
}
//希尔排序
int
d = a.length;
while
(
true
){
d = d /
2
;
for
(
int
x=
0
;x<d;x++){
for
(
int
i=x+d;i<a.length;i=i+d){
int
temp = a[i];
int
j;
for
(j=i-d;j>=
0
&&a[j]>temp;j=j-d){
a[j+d] = a[j];
}
a[j+d] = temp;
}
}
if
(d ==
1
){
break
;
}
}
System.out.println();
System.out.println(
"排序之后:"
);
for
(
int
i =
0
; i < a.length; i++) {
System.out.print(a[i]+
" "
);
}
}
}