排序算法之选择排序

一.直接选择排序

直接选择排序的只要思想是遍历数组,将数中的最大值和数组最后一位交换,然后出了最后一位的剩余数组遍历选出最大的放在数组剩余数组的最后一位。以此类推。变可以得到排序之后的数组,用图表示如下是:

1:[2, 5, 1, 4, 3, 6, 7]------原始数据

2:[2, 5, 1, 4, 3, 6,7]

3:[2, 5, 1, 4, 3,6, 7]

4:[2, 3, 1, 4, 5, 6, 7]

5:[2, 3, 1, 4, 5, 6, 7]

6:[2, 1, 3, 4, 5, 6, 7]

7:[1,2, 3, 4, 5, 6, 7]

java代码如下:

<span style="font-size:18px;"><span style="white-space:pre">	</span>public static void chooseSort(int[] data){
		
		//从后往前遍历,用来排序数组
		for (int i = data.length-1; i > 0; i--) {
			//将剩余数组最后一位做为带比较的第一个数
			int max = data[i];
			//用来记录最大数的位置,方便遍历完了之后交换位置
			int j = i;
			//这个遍历用来寻找最大数和几率最大数的位置下标
			for (int k = i-1; k >= 0; k--) {
				//如果比最大数大则更换最大数并记录位置
				if(max < data[k]){
					max = data[i];
					j = k;
				}
			}
			//最大数和剩余数组最后一位交换位置
			int temp = data[i];
			data[i] = data[j];
			data[j] = temp;
		}
	}</span>


二.堆排序

说到堆排序就要用到二叉树的相关知识。类似于完全二叉树。堆又分最大堆和最小堆,最大堆就是父节点总是大于等于子节点,最小堆则相反。下图就是最小堆:


上图的数据在数组的存放顺序为[1, 2, 3, 17, 19, 36, 7, 25, 100]。由图可以发现一个规律,加入父节点的下标为i则左子节点的下标为2*i+1,右子节点的下标为2*i+2。

假如子节点的下表为i,则该父节点的下标为(i-1)/2。最后一位数100的下标是8,则父节点的下标为(8-1)/ 2 = 3,下标为3的是17,17之后的数都是子节点。假设4有子节点,那么他的左子节点下标为4/ 2+1 = 9,已经越界了。

首先假如有这么一个数组[9, 12, 17, 30, 50, 20, 60,  65, 4, 49]要求按最小堆排序。排序思路如下:

很明显,对叶子结点来说,可以认为它已经是一个合法的堆了即20,60, 65, 4, 49都分别是一个合法的堆。只要从A[4]=50开始向下调整就可以了。然后再取A[3]=30,A[2] = 17,A[1] = 12,A[0] = 9分别作一次向下调整操作就可以了。下图展示了这些步骤:


java代码如下:

    <span style="font-size:18px;">public static void heapSort(int[] array) {  
         if (array == null || array.length <= 1) {  
             return;  
         }  

         //构建最大堆
         buildMaxHeap(array);
         
         //开始排序,升序排列
         for (int i = array.length - 1; i >= 1; i--) {  
             ArrayUtils.exchangeElements(array, 0, i);  

             maxHeap(array, i, 0);  
         }
     }  </span>

<span style="font-size:18px;">     <span style="white-space:pre">	</span>/**
	  * 构建最大堆
	  * @param array
	  */
     private static void buildMaxHeap(int[] array) {  
         if (array == null || array.length <= 1) {  
             return;  
         }  

         int half = array.length / 2;
         for (int i = half; i >= 0; i--) {  
             maxHeap(array, array.length, i);  
         }  
     }  </span>

<span style="font-size:18px;">    private static void maxHeap(int[] array, int heapSize, int index) {  
         int left = index * 2 + 1;//左节点
         int right = index * 2 + 2;//右节点

         int largest = index;//largest用来存放父节点,左右节点中最大的那个
         if (left < heapSize && array[left] > array[index]) {
             largest = left;  
         }  

         if (right < heapSize && array[right] > array[largest]) {  
             largest = right;  
         }  

         //如果父节点不是最大值则交换父节点和最大值的位置,并把最大值作为父节点递归调用maxHeap
         if (index != largest) {  
             ArrayUtils.exchangeElements(array, index, largest);  

             maxHeap(array, heapSize, largest);  
         }  
     } </span>


参考文章地址:http://blog.csdn.net/morewindows/article/details/6709644/

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值