选择排序(二)--树形选择排序《 转载》

本文深入探讨了利用满二叉树性质实现的树形选择排序算法,详细解释了满二叉树与完全二叉树的区别,展示了算法的程序讲解与具体实现过程,包括满二叉树的数据结构设计、程序流程解析及满二叉树叶子节点数量计算方法。
 

选择排序(二)--树形选择排序

分类: 算法相关 C/C++   314人阅读  评论(0)  收藏  举报

利用满二叉树的性质,思想:将输入的数据存放到满二叉树的叶节点,通过比较树中剩余可用节点(从底层的叶节点开始)的大小,每次选择最小的数值(比较复制到二叉树的顶端),并且把最小数值赋给排序数组的前端,把最小数值原来叶节点的位置设置为不可用;依次循环直至最后一个可用叶节点。

一、满二叉树和完全二叉树区别如图:

未命名6 
二、程序讲解:

template 
class TreeNode{ 
public: 
    T data; 
    int index; 
    int active; 
    TreeNode & operator=(TreeNode & treenode) 
    { 
        this->data=treenode.data; 
        this->index=treenode.index; 
        this->active=treenode.active; 
        return *this; 
    } 
}; 
树节点数据结构包括了data数值,index用来存放该数值在叶节点存放的位置(所有数据开始都是存放在叶节点),active表示激活没有,最后如果该数据移植树根部,则将active字段置0无效。

[cpp]  view plain copy
  1. /*2)树形排序 */  
  2. template <class T>  
  3. void ChangeTree(TreeNode<T> * tree,int i)  
  4. {  
  5.     if(i%2==0)  
  6.         tree[(i-1)/2]=tree[i-1];  
  7.     else  
  8.         tree[(i-1)/2]=tree[i+1];  
  9.     i=(i-1)/2;  
  10.     int j;  
  11.     while(i)  
  12.     {  
  13.         if(i%2==0)  
  14.             j=i-1;  
  15.         else  
  16.             j=i+1;  
  17.         if(!tree[i].active || !tree[j].active)  
  18.             if(tree[i].active)  
  19.                 tree[(i-1)/2]=tree[i];  
  20.             else  
  21.                 tree[(i-1)/2]=tree[j];  
  22.         else  
  23.             if(tree[i].data<tree[j].data)  
  24.                 tree[(i-1)/2]=tree[i];  
  25.             else  
  26.                 tree[(i-1)/2]=tree[j];  
  27.         i=(i-1)/2;  
  28.     }  
  29. }  
  30. int Power(int n)  
  31. {  
  32.   int result=1;  
  33.   if(n>=1)  
  34.   {  
  35.       for(int i=1;i<=n;i++)  
  36.           result *=2;  
  37.       return result;  
  38.   }  
  39.   else   
  40.       return 1;  
  41. }  
  42. int LeapNum(int n) //计算满足满二叉树的叶子节点数  
  43. {  
  44.     for(int i=1;i<100;i++)  
  45.         if(Power(i-1)<n && n<Power(i))   
  46.             return Power(i);  // i 为层数, Power(i) 为叶节点数  
  47.         else if(Power(i-1)==n)  
  48.             return Power(i-1);  
  49. }  
  50. int log(int n)  
  51. {  
  52.     for(int i=1;i<100;i++)   
  53.         if(Power(i-1)==n)  
  54.             return i-1;  
  55.     return -1;  
  56. }  
  57. template<class T>  
  58. void DisplayTree(TreeNode<T> tree[],int size)  
  59. {  
  60. int temp=0,biggestGap,gap;  
  61. biggestGap=(size+1)/2-1;  
  62.     for(int i=0;i<size;i++)  
  63.     {  
  64.         if((log(i+1))!=-1)  
  65.         {   cout<<"/n";  
  66.             gap=biggestGap;  
  67.             for(int k=0;k<temp;k++)  
  68.                gap=(gap-1)/2;  
  69.             for(int j=0;j<gap;j++)  
  70.                 cout<<"   ";  
  71.             temp++;  
  72.         }  
  73.         if(tree[i].active)  
  74.           cout<<tree[i].data<<"   ";  
  75.         else  
  76.             cout<<"#  ";  
  77.     }  
  78. }  
  79. template<class T>  
  80. void TreeSort(T a[],int n)  
  81. {  
  82.     TreeNode<T> * tree;  
  83.     int bottsize=LeapNum(n); //满二叉树的底层叶子数,必须为 满二叉树  
  84.     int size=2*bottsize-1; //满二叉树中结点总数  
  85.     int externalIndex=bottsize-1; //开始进行比较的节点位置  
  86.     tree=new TreeNode<T> [size];  
  87.     assert(tree);  
  88.     int j=0;  
  89.     int i;  
  90.     for( i=externalIndex;i<size;i++)  
  91.     {  
  92.         tree[i].index=i;  
  93.         if(j<n)  
  94.         {  
  95.             tree[i].active=1;       //设置访问标志,1可以访问  
  96.             tree[i].data=a[j++];    //载入数据  
  97.         }  
  98.         else  
  99.             tree[i].active=0;  //额外设置的节点,不可访问  
  100.     }  
  101.     i=externalIndex;    //externalIndex用来指向树的叶节点的最左部分的位置,i每次往上一层的最左位置移动  
  102.     while(i)           //比较找到最小节点  
  103.     {  
  104.        j=i;  
  105.        while(j<2*i)  
  106.        {  
  107.           
  108.           if(!tree[j+1].active || tree[j].data <= tree[j+1].data)  
  109.           {  
  110.                if(!tree[j+1].active && !tree[j].active)  
  111.                {  
  112.                    tree[(j-1)/2].active=0; //其孩子节点都是额外节点,不可访问  
  113.                }  
  114.                tree[(j-1)/2]=tree[j];  //较小节点赋值给其双亲节点  
  115.           }  
  116.           else  
  117.               tree[(j-1)/2]=tree[j+1];  
  118.           j+=2;  
  119.        }  
  120.        i=(i-1)/2;  
  121.     }  
  122.     for(i=0;i<n-1;i++)   //处理前面n-1个节点  
  123.     {  
  124.         DisplayTree(tree,size);//zhou add   
  125.         a[i]=tree[0].data;            
  126.         tree[tree[0].index].active=0;//不在参加比较  
  127.         ChangeTree(tree,tree[0].index);//修改树形结构,使得参加比较的最小的数据移到树根部  
  128.     }  
  129.     DisplayTree(tree,size);//zhou add   
  130.     a[n-1]=tree[0].data;  //数值最大的节点  
  131. }  
  132. template <class T>  
  133. void Output(T a[],int n)  
  134. {  
  135.     for(int i=0;i<n;i++)  
  136.         cout<<a[i]<<"/t";  
  137.     cout<<"/n";  
  138. }  
 

具体的程序每次交换的输出如下,

输入数据时:1541,54, 89,345  , 416,1

#表示叶节点处无效的位置,

一次排序后参加排序(有效的)的数据移到最顶端(树根)

未命名6


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值