树形选择排序算法

树形选择排序有时也称为锦标赛排序。排序过程中,按照锦标赛比赛规则进行,将所有n个数据看成一棵完全二叉树的叶子结点,首先,完全二叉树的叶子结点两两比较,胜出的兄弟进入树的上一层继续和兄弟进行比较,如果某个叶子结点没有兄弟,则直接进入上一层,一直到二叉树的第二层的两个兄弟节点进行比较,胜出者为第一名。为了产生第二名,可将刚刚的到的第一名看成是最差的。再从此结点到根的路径上依次和相应的兄弟结点进行比较,最终得到树根,而得到第二民,依次下去,可得到第三名,第四名,......,最终得到最后的排名。

	public static void main(String args[]){
		int a[] ={1,9,5,6,11,2,7,32,3,15};
//		simpleSelectSort(a);
		List list = new ArrayList<>();
		for(int i=0;i<a.length;i++){
			list.add(a[i]);
		}
//		treeSelectGroup(list);
		treeSelectSort(list);
	}
/**
	 * 树形选择排序
	 * 算法思想:树形选择排序有时也称为锦标赛排序。排序过程中,按照锦标赛比赛规则进行,将所有n个数据看成一棵完全二叉树的叶子结点,
	 * 首先,完全二叉树的叶子结点两两比较,胜出的兄弟进入树的上一层继续和兄弟进行比较,如果某个叶子结点没有兄弟,则直接进入上一层,
	 * 一直到二叉树的第二层的两个兄弟节点进行比较,胜出者为第一名。为了产生第二名,可将刚刚的到的第一名看成是最差的。再从此结点到根
	 * 的路径上依次和相应的兄弟结点进行比较,最终得到树根,而得到第二民,依次下去,可得到第三名,第四名,......,最终得到最后的排名。
	 * @param a 排序的数组
	 */
	public static void  treeSelectSort(List<Object> list){
	
			System.out.println("开始树形选择排序:" + list.toString());
			List<Object> treeList = createATree(list);//先生成一个树,每一层用ArrayList存着
			int size = list.size() -1;//总共要进行将最大值替换成最小值的次数
			
			System.out.println(treeList.toString());
			for(int i=0;i<size;i++){
				replaceTreeMax2Min(treeList);
			}
			
			
			
	} 


/**
	 * 树形选择排序中生成一颗树
	 * @param list 要生成树的list
	 * @return List<Object> 生成后的树,存储每一层的数据
	 */
	public static List<Object> createATree(List<Object> list){	
		int n = (int) (Math.log(list.size())/Math.log(2));//先计算需要比较的次数		
		int sIndex = 0;//第一次开始遍历的位置
		int eIndex = (int)Math.pow(2, n);//第一次结束遍历的位置,为2的n次方
		List<Object> treeList = new ArrayList<>();//每遍历一层,都将数据存入当中
		List<Object> nextList = new ArrayList<>();//下一层的数据
		for(int i=0;i<=n;i++){
			List<Object> nowList = new ArrayList<>();//当前层的数据
			nowList.addAll(nextList) ;//当前层先取上一层比较后的数据 
			nextList.clear();//将上一层比较后的数据清零
			if(i==0){//如果是第一层
				nowList.addAll(list.subList(sIndex, eIndex));	
			}else if(i ==1){//如果是第二层
	
			if(eIndex < list.size()){//如果第一层遍历的时候有数据没有进行遍历
					n+=1;//要多遍历一层
					nowList.addAll(list.subList(eIndex,list.size()));	//将第一次没有遍历的数据加入到第二层当中遍历
			}				
		}
			treeList.add(nowList);//将当前层的数据加入treeList当中
			for(int j=0;j<nowList.size();j+=2){//把数据两两分成一组进行对比
				Object o1 = nowList.get(j);
				
				if(j+1 >=nowList.size()){//判断数据是否越界,越界直接退出循环
					nextList.add(o1);
					break;
				}
				Object o2 = nowList.get(j+1);
								
				if(Integer.parseInt(o1.toString()) > Integer.parseInt(o2.toString())){//判断哪个数据大,将数据大的加入下一层循环
					nextList.add(o1);
				}else{
					nextList.add(o2);
				}
			}
		}
		return treeList;
		

	}


	/**
	 * 将一个树当中的最大值替换成最小值,继续比较,找到其中的最大值
	 * @param treeList 需要替换的树
	 */
	public static void replaceTreeMax2Min(List<Object> treeList){
		int n = treeList.size();//总共的层数
		List<Object> listLast = (List<Object>) treeList.get(n -1);//获取最后一层的list
		Object oMax = listLast.get(0);//获取最大的一个数据
		Object oMin = "0";//设置的最小值
		Object oResult = oMin;//当前层比较的结果,默认值为0
		
		for(int i=0;i<n;i++){//遍历每一层
			List<Object> nowList = (List<Object>)treeList.get(i);//获取当前一层
			
			for(int j=0;j<nowList.size();j++){//在当前层找到最大的值
				if(nowList.get(j).equals(oMax)){//在当前行找到最大的值
					nowList.set(j, oResult);//将最大值设置为上一层的比较结果
					
					if(j%2 == 0){//如果当前的最大值位置为偶数,让其与右边一位比较
						if(j+1 <nowList.size()){//判断数据是否越界,如果没有越界
							oResult = (Integer.parseInt(nowList.get(j).toString())> Integer.parseInt(nowList.get(j+1).toString()))? nowList.get(j):nowList.get(j+1);//下一层的要替换的值为当前两者之间最大的一位
						}else{//数组越界了
							oResult = nowList.get(j);//下一层要替换的值为当前的值
						}
					}else{//如果当前位置为奇数,让其与左边一位比较		
						oResult = (Integer.parseInt(nowList.get(j).toString())> Integer.parseInt(nowList.get(j-1).toString()))? nowList.get(j):nowList.get(j-1);//下一层的要替换的值为当前两者之间最大的一位
					}
				}
				
			}
		}
		System.out.println(treeList.toString());
	}
	


下面看执行的结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值