选择排序(直接、堆)

package com.jason.sort.arithmethic;

import java.util.Arrays;

/**
 * 选择排序分为直接排序和堆排序 从第一个位置开始定位比较,大于该位置的值则交换,经过第一轮排序最小值定位在第一位
 * 一次类推n-1次排序,最后一位依然是最大值。
 * 
 * @author mk
 * 
 */
public class SelectSort
{
public static void main(String[] args)
{
DataWrap[] dws = { new DataWrap(10, ""), new DataWrap(5, ""),
new DataWrap(8, ""), new DataWrap(3, ""),new DataWrap(14, "") };
System.out.println("排序前:" + Arrays.toString(dws));
sortDirect(dws);
System.out.println("排序后:" + Arrays.toString(dws));
/**
* 直接排序测试结果:
*  第 0 趟排序后:[3, 5, 8, 10, 14]
* 第 1 趟排序后:[3, 5, 8, 10, 14] 
* 第 2 趟排序后:[3, 5, 8, 10, 14] 可以看出不稳定
* 第 3 趟排序后:[3, 5, 8, 10, 14] 可以看出不稳定
*/

dws = new DataWrap[] { new DataWrap(9, ""), new DataWrap(79, ""),
new DataWrap(46, ""), new DataWrap(49, ""), new DataWrap(30, ""),new DataWrap(58, "") };
sortHeap(dws);
/** 堆排序测试结果
* 排序前:[9, 79, 46, 49, 30, 58]
* 第 0 趟排序后:[46, 49, 58, 9, 30, 79]
* 第 1 趟排序后:[30, 49, 46, 9, 58, 79]
* 第 2 趟排序后:[9, 30, 46, 49, 58, 79]
* 第 3 趟排序后:[9, 30, 46, 49, 58, 79]
* 第 4 趟排序后:[9, 30, 46, 49, 58, 79]
* 排序后:[9, 30, 46, 49, 58, 79]
*/
}


// 直接排序,简单、性能较差,改进版,保存最小值索引,使交换次数减少,时间效率O(n2),时间效率O(1),不稳定的
public static void sortDirect(DataWrap[] datas)
{
for (int i = 0; i < datas.length - 1; i++)
{
int minIndex = i;// 保存最小值索引
for (int j = i + 1; j < datas.length; j++)
{
if (datas[minIndex].compareTo(datas[j]) > 0)
minIndex = j;
}
// 保证每趟排序最小值在当前位置
if (minIndex != i) swap(datas, minIndex, i);
System.out.println("第 "+i+" 趟排序后:" + Arrays.toString(datas));
}
}


// 堆排序相对效率更好,实现稍复杂,第一步建堆;第二步拿堆的根节点和最后一节点交换。堆排序时间效率O(nlog2n(底数2,指数n)),空间效率O(1)
public static void sortHeap(DataWrap[] datas)
{
System.out.println("排序前:" + Arrays.toString(datas));
for(int i=0; i<datas.length-1; i++)
{
buildMaxHeap(datas, datas.length-1-i);// 循环建堆
swap(datas, 0, datas.length-1-i);// 交换堆顶和最后一个元素
System.out.println("第 "+i+" 趟排序后:" + Arrays.toString(datas));
}
System.out.println("排序后:" + Arrays.toString(datas));
}

private static void buildMaxHeap(DataWrap[] datas, int lastIndex)
{
for(int i=(lastIndex -1)/2; i>=0 ; i--)
{
int k = i;// 保存当前判断的节点
// 当前k节点存在子节点
while((2 * k + 1) <= lastIndex)
{
// k节点的左子节点
int biggerIndex = 2 * k + 1;
// 表示k的节点存在右子节点
if(biggerIndex < lastIndex)
if(datas[biggerIndex].compareTo(datas[biggerIndex+1]) < 0)
biggerIndex ++;// 记录最大的子节点

if(datas[k].compareTo(datas[biggerIndex])<0)
{
swap(datas, k, biggerIndex);
k = biggerIndex;// 再次循环使用k节点大于新的子节点
}
else
break;
}
}
}

// 交换数据
private static void swap(DataWrap[] datas, int i, int j)
{
DataWrap tmp = datas[i];
datas[i] = datas[j];
datas[j] = tmp;
}
}

/**
 * 排序封装的数据包
 * @author mk
 *
 */
class DataWrap
{
private int data;
private String flag;
public DataWrap(int data, String flag)
{
this.data = data;
this.flag = flag;
}
// 根据data的实例变量决定两个DataWrap的大小
public int compareTo(DataWrap dw)
{
return this.data > dw.data ? 1 : (this.data == dw.data ? 0 : -1);
}

@Override
public String toString()
{
return data + flag;
}
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值