码迷,mamicode.com
首页 > 编程语言 > 详细

POJ-1002: 487-3279 详解1: 堆排序法

时间:2015-08-02 11:37:34      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

> 分析
  >> 本题的难点在于排序速度上
  >> 排序算法要考虑重复项很多,无重复项两种情况
  >> 当然由于本题对内存占用的要求不高,也可以不使用排序
 

> 总体思路

  >> 先将电话号码按输入的顺序存下来
  >> 对所有号码使用堆排序
  >> 排序后根据号码连续出现的频率输出频率大于1的号码
 
> 输入转换
  >> 本题中已详细定义了字母到数字的映射,因此推荐使用映射表较快
 
> 存储形式
  >> 由于涉及到排序比较,因此推荐电话号码以整型存储,不使用字符串
 
> 排序
  >> 考虑到可能出现很多重复的号码,因此推荐使用堆排序
  >> 快速排序在处理重复项过多时效率脚底
 
> 附代码
/*---------------------------------
 * 堆排序,输出时计算出现频率
 *---------------------------------*/
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

/* 字母到数字的映射表 */
const int map[26] = {
    2, 2, 2,    /* A, B, C */
    3, 3, 3,    /* D, E, F */
    4, 4, 4,    /* G, H, I */
    5, 5, 5,    /* J, K, L */
    6, 6, 6,    /* M, N, O */
    7, 0, 7, 7, /* P, Q, R, S */
    8, 8, 8,    /* T, U, V */
    9, 9, 9,    /* W, X, Y */
    0           /* Z */
} ;


/* 存储出现的所有电话号码 */
int teleNum[100000] = {0} ;

void exchange(int *p1, int *p2)
{
    int tmp = *p1 ;
    *p1 = *p2 ;
    *p2 = tmp ;
}

/* 保持最大堆的性质(非递归) */
void maxHeapify(int *pStart, int size, int i)
{
    int left = 0 ;
    int right = 0 ;
    int largest = 0 ;

    largest = i ;

    do 
    {
        i = largest ;
        left = 2 * i + 1 ;
        right = 2 * i + 2 ;
    
        if(left < size && pStart[left] > pStart[largest])
            largest = left ;

        if(right < size && pStart[right] > pStart[largest])
            largest = right ;

        if(largest != i)
            exchange(&pStart[i], &pStart[largest]) ;

    }while(largest != i) ;
}

/* 堆排序 */
void sort(int *pStart, int size)
{
    int i = 0 ;
    
    for(i = size/2 - 1; i >= 0; i--)
        maxHeapify(pStart, size, i) ;

    for(i = size - 1; i > 0; i--)
    {
        exchange(&pStart[0], &pStart[i]) ;
        maxHeapify(pStart, i, 0) ;
    }    
}

int main(void)
{
    int  n = 0 ;
    char s[50] = {0} ;
    int  num = 0 ;
    int  i = 0, j = 0 ;
    int  count = 0 ;
    char flag = 0 ;

    scanf("%d", &n) ;
    for(i = 0; i < n; i++)
    {
        memset(s, 0, sizeof(s)) ;
        scanf("%s", s) ;        

        /* 将电话号码转换为整型 */
        num = 0 ;
        for(j = 0; j < sizeof(s); j++)
        {
            if(0 == s[j])
                break ;
            if(Q == s[j] || Z == s[j])
                continue ;
            if(s[j] >= A && s[j] <= Z)
                num = num * 10 + map[s[j] - A] ;
            if(s[j] >= 0 && s[j] <= 9)
                num = num * 10 + s[j] - 0 ;
        }
        
        teleNum[i] = num ;
    }

    sort(teleNum, n) ;

    flag = 0 ;
    num = teleNum[0] ;
    count = 1 ;
    for(i = 1; i < n; i++)
    {
        if(teleNum[i] != num)
        {
            if(count > 1)
            {
                flag = 1 ;

                printf("%03d-%04d %d\r\n", num / 10000,
                    num % 10000, count) ;
            }
            
            num = teleNum[i] ;
            count = 1;
        }
        else
            count++ ;
    }

    if(count > 1)
    {
        flag = 1 ;

        printf("%03d-%04d %d\r\n", num / 10000,
            num % 10000, count) ;
    }

    if(0 == flag)
        printf("No duplicates.\r\n") ;

    return 0 ;
}

 

POJ-1002: 487-3279 详解1: 堆排序法

标签:

原文地址:http://www.cnblogs.com/codesworld/p/4695282.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!