惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
P
Proofpoint News Feed
宝玉的分享
宝玉的分享
人人都是产品经理
人人都是产品经理
博客园_首页
爱范儿
爱范儿
博客园 - 叶小钗
aimingoo的专栏
aimingoo的专栏
S
SegmentFault 最新的问题
MyScale Blog
MyScale Blog
阮一峰的网络日志
阮一峰的网络日志
IT之家
IT之家
Microsoft Security Blog
Microsoft Security Blog
Blog — PlanetScale
Blog — PlanetScale
博客园 - 【当耐特】
Y
Y Combinator Blog
量子位
博客园 - 三生石上(FineUI控件)
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
The Blog of Author Tim Ferriss
月光博客
月光博客
有赞技术团队
有赞技术团队
Apple Machine Learning Research
Apple Machine Learning Research
A
About on SuperTechFans

博客园 - gxc

C#2.0中的泛型约束(转载) 解决‘“System.Configuration.ConfigurationSettings.AppSettings”已过时’的警告 《雷神之锤III》里求平方根倒数的函数 回溯法(vc)百鸡百钱问题 回溯法(vc)八皇后问题 六十六条经典禅语 prototype.js和Ajax 悖论 标签的使用(2) 标签的使用(1) 自底向上的归并排序 自顶向下的归并排序 归并排序之归并算法 Josephus问题(循环链表) 找质数算法(Sieve of Eratosthenes筛法) 直接选择排序 快速排序算法 Some of the new features from ASP.NET 2.0 在ASP.NET中使用AJAX
堆排序
gxc · 2005-12-24 · via 博客园 - gxc

        先给出大根堆的定义:完全二叉树,任一非叶子结点都大于等于它的孩子,也就是说根结点是最大的。而且显然大根堆的任一棵子树也是大根堆。
        堆排序的基本思想是:记录区的分为无序区和有序区前后两部分;用无序区的数建大根堆,得到的根(最大的数)和无序区的最后一个数交换,也就是将该根归入有序区的最前端;如此重复下去,直至有序区扩展至整个记录区。
具体操作可按下面步骤实现:
1。建大根堆
2。交换根和无序区最后一个数
3。重建大根堆,因为交换只是使根改变了,所以左右子树依然分别是大根堆。
4。比较根,左子树的根和右子树的根,如果根最大,则无须再作调整,树已经是大根堆了;如果左子树的根最大,交换它与根,再递归调整左子树;如果右子树的根最大,交换它与根,再递归调整右子数。
5。递归调整到叶子的时候,树就是大根堆了。
        现在还要解决的就是如何建那个初始的大根堆了,把整个数组R0,R1,...,R(n-1)看成一个完全二叉树,只要从后往前依次将以该结点为根的子树调整为大根堆就行了。而实际上,序号大于[n/2]的结点都是叶子结点,可看作是大根堆,所以只需调整[n/2],[n/2]-1,...,1的结点作为根节点的子树就可以了。
public static void HEAPSORT(int[] R)
{
    //建初始大根堆
    for (int i = R.Length / 2+Convert.ToInt32(Math.IEEERemainder(R.Length,2)); i >0 ; i--)
    {
        SIFT(R, i-1, R.Length-1);
    }
    //循环进行交换并重建大根堆
    for (int j = R.Length - 1; j > 0; j--)
    {
        //交换根和无序区最后一个数
        int t = R[0]; R[0] = R[j]; R[j] = t;
        SIFT(R, 0, j-1);
    }   
}
public static void SIFT(int[] R,int iFrom,int iTo)
{
    int i = iFrom;            //根结点下标
    int j = 2 * iFrom + 1;    //左孩子下标
    int temp = R[i];          //要调整的根结点,假定左右子树已为大根堆
    while (j <= iTo)
    {
        if ((j < iTo) && ((R[j] < R[j + 1])))
        {
            j++;//如果右孩子大于左孩子,将j指向右孩子,以便接下来统一处理
        }
        if ((R[j] > temp))
        {
            //比根结点大的孩子上移
            R[i] = R[j];
            //指向下一个子树
            i = j;
            j = 2 * i + 1;
        }
        else
        {
            break;
        }
    }
    //定位要当初的根结点到正确的位置
    R[i] = temp;
}