找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3558|回复: 0

C++锦标赛排序算法改进

[复制链接]

307

主题

228

回帖

7343

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5593 个
贡献
253 次
宅之契约
0 份
在线时间
948 小时
注册时间
2014-1-25
发表于 2014-7-27 22:31:01 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
    看了东南大学那个算法视频,知道了锦标赛排序算法的原理,在网上搜了一下,实现的比较少代码也不够规范。
先简要说一下原理:锦标赛算法是选择排序改进的,充分利用前面选择最小值的比较步骤,去除后面冗余的比较。比如你在前一遍已经比较出了
a1<a2了,后面你应该想直接用这个结果,而不是再比较一次,因此这些比较值存储于一颗完全二叉树中,这棵树记载了两两比较的结果,这样,
前面比较之后,就可以利用前面的结果进行比较,而且只需要遍历上次改动的一个分支。将最小的节点逐层比较通过0号元素输出,并把这个元素
对应于原数组在二叉树中的位置标记为无穷大,并从该叶节点的父节点开始比较,这样循环直到全部输出为止。原视频中说存储的直接是值,然而
实际操作中发现并不方便,因为根据值不好判断他的索引是什么,去除的时候也不是随便去除而是找你产生最小值的分支进行去除,否则会出错。
我这种方法在二叉树中记录的是索引,元素的去除就会将索引标记为一个特殊的数。如果是内建的排序算法,那么你可以直接吧这个位置并到数组中,
将该索引位置的值赋值为无穷大,但是考虑到通用性,我没有这么做,于是就要判断索引值是否合法了。如果内建的算法的话,效率估计会更高。
代码如下:
  1. // test.cpp : Defines the entry point for the console application.
  2. //

  3. #include "stdafx.h"

  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <iostream>
  7. #include <stack>
  8. #include <vector>
  9. using namespace std;

  10. void main()
  11. {
  12.         const int size=17;
  13.         int data[size];

  14.         int j;
  15.         int k;
  16.        
  17.         for(k=0;k<size;k++)
  18.         {
  19.                 data[k]=rand()&0xFF;
  20.                 printf("%d ",data[k]);
  21.         }
  22.         printf("\n");
  23.        

  24. #define MAX 256//只要比数组大就可以
  25.         vector<int> treedata;//二叉树
  26.         int volumn=2;

  27.         while(volumn < size)
  28.                 volumn *= 2;

  29.         int newsize=volumn-1+size;//计算完全二叉树容量

  30.         vector<int> copydata;

  31.         treedata.resize(newsize);
  32.         for(int i=0;i < volumn-1;i++)
  33.         {
  34.                 treedata[i]=MAX;//根据需要调整该值,只要大于原数组容量即可
  35.         }

  36.         for(i=0;i<size;i++)
  37.         {
  38.                 treedata[i+volumn-1]=i;
  39.         }

  40.         for(j=0;j<newsize;j++)
  41.         {
  42.                  cout<<treedata[j]<<" ";
  43.         }
  44.         cout<<endl;
  45.         cout<<"newsize:"<<newsize<<endl;

  46.         //生成初始树  总长度为newsize
  47.         for(i=volumn-2;i >= 0;i--)
  48.         {
  49.                 if(i*2+1 < newsize && treedata[i*2+1] != MAX)//有左子树且合法
  50.                 {//如果没有左子树,根据完全二叉树性质,肯定没有右子树,同理初始化时,如果左子树为MAX,那么右子树一定是MAX
  51.                         int tochange=i*2+1;
  52.                         if(i*2+2 < newsize && treedata[i*2+2] != MAX)//如果有右子树
  53.                         {
  54.                                 if(data[treedata[i*2+2]] < data[treedata[tochange]])
  55.                                         tochange=i*2+2;
  56.                         }
  57.                         treedata[i]=treedata[tochange];
  58.                 }
  59.         }

  60.         int left=size;
  61.         while(left--) //做size次
  62.         {
  63.                 if(left == 8)
  64.                 {
  65.                         int a=0;
  66.                         cout<<treedata[0]<<endl;
  67.                         cout<<data[treedata[0]]<<endl;
  68.                 }
  69.                 copydata.push_back(data[treedata[0]]);
  70.                 int index=volumn-1+treedata[0];//索引位置
  71.                 treedata[index]=MAX;
  72.                 //从索引位置往父节点递归
  73.                 do
  74.                 {
  75.                         index = (index-1)/2;//得到父节点
  76.                         treedata[index]=MAX;//重置父节点

  77.                         if(index*2+1 < newsize)//有左子树
  78.                         {//仍然是如果没有左子树肯定没有右子树
  79.                                 int tochange=index*2+1;//可能为MAX
  80.                                 if(index*2+2 < newsize && treedata[index*2+2] != MAX)
  81.                                 {
  82.                                         if(treedata[tochange] == MAX ||
  83.                                                         (treedata[tochange] != MAX && data[treedata[tochange]] > data[treedata[index*2+2]]))
  84.                                                 tochange=index*2+2;
  85.                                 }
  86.                                 treedata[index]=treedata[tochange];//可能赋值为MAX
  87.                         }
  88.                 }
  89.                 while(index);
  90.         }

  91.         for(j=0;j<newsize;j++)
  92.         {
  93.                 cout<<treedata[j]<<" ";
  94.         }
  95.         cout<<endl;


  96.         for(j=0;j<copydata.size();j++)
  97.         {
  98.                 data[j]=copydata.at(j);
  99.         }
  100.         printf("\n");


  101.         for(k=0;k<size;k++)
  102.         {
  103.                 printf("%d ",data[k]);
  104.         }
  105.         printf("\n");
  106.        
  107.         getchar();
  108. }

复制代码
回复

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-29 05:41 , Processed in 0.038541 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表