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

> 分析

>> 本题的难点在于排序速度上

>> 排序算法要考虑重复项很多,无重复项两种情况

>> 当然由于本题对内存占用的要求不高,也可以不使用排序

> 总体思路

>> 先将电话号码按输入的顺序存下来

>> 对所有号码使用堆排序

>> 排序后根据号码连续出现的频率输出频率大于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 ;
}
时间: 2024-11-08 02:33:33

POJ-1002: 487-3279 详解1: 堆排序法的相关文章

POJ-1007: DNA Sorting 详解1: 插入排序法

> 分析 >> 本题分两步 1. 计算序列的逆序数 2. 根据逆序数排序 >> 由于序列个数最大只有100个, 所以不需要过分追求速度,插入排序就够用 > 注意: >> 存储序列的数组长度最好是50+1, 有利于输出 > 附代码 1 #include "stdio.h" 2 3 int main(void) 4 { 5 char seqs[100][50 + 1] = {0} ; 6 int inversions[100] = {0

Heapsort 堆排序算法详解(Java实现)

Heapsort (堆排序)是最经典的排序算法之一,在google或者百度中搜一下可以搜到很多非常详细的解析.同样好的排序算法还有quicksort(快速排序)和merge sort(归并排序),选择对这个算法进行分析主要是因为它用到了一个非常有意思的算法技巧:数据结构 - 堆.而且堆排其实是一个看起来复杂其实并不复杂的排序算法,个人认为heapsort在机器学习中也有重要作用.这里重新详解下关于Heapsort的方方面面,也是为了自己巩固一下这方面知识,有可能和其他的文章有不同的入手点,如有错

POJ 1659 Frogs&#39; Neighborhood(可图性判定—Havel-Hakimi定理)【超详解】

Frogs' Neighborhood Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 9897   Accepted: 4137   Special Judge Description 未名湖附近共有N个大小湖泊L1, L2, ..., Ln(其中包括未名湖),每个湖泊Li里住着一只青蛙Fi(1 ≤ i ≤ N).如果湖泊Li和Lj之间有水路相连,则青蛙Fi和Fj互称为邻居.现在已知每只青蛙的邻居数目x1, x2, ..

poj 1611(详解)

The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 22217   Accepted: 10805 Description Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. T

数据结构 - 堆排序(heap sort) 详解 及 代码(C++)

堆排序(heap sort) 详解 及 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 堆排序包含两个步骤: 第一步: 是建立大顶堆(从大到小排序)或小顶堆(从小到大排序), 从下往上建立; 如建堆时, s是从大到小; 第二步: 是依次交换堆顶和堆底, 并把交换后的堆底输出, 只排列剩余的堆, 从上往下建立; 如构造时, s始终是1; 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: S

poj 1942(详解)

Paths on a Grid Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21439   Accepted: 5259 Description Imagine you are attending your math lesson at school. Once again, you are bored because your teacher tells things that you already mastere

linux查看端口及端口详解

今天现场查看了TCP端口的占用情况,如下图 红色部分是IP,现场那边问我是不是我的程序占用了tcp的链接,,我远程登陆现场查看了一下,这种类型的tcp链接占用了400多个,,后边查了一下资料,说ESTABLISHED状态 ESTABLISHED的意思是建立连接.表示两台机器正在通信.      之后查找  ncube-lm  发现ncube-lm是一个端口,是nCube License Manager (即ncube管理的一个许可证明),意思是被允许,被认证开放的意思,,, 之后查看端口号 是1

Spring事务管理(详解+实例)

写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都

Linux系统DNS详解(BIND)

一.Linux运维实战之DNS基础    DNS服务作为网络的一种基础架构,在网络中有举足轻重的地位.它担负着整个网络用户计算机的名称解析工作.没有正确的名称解析,服务器就无法识别各客户机.我们在日常进行的浏览网页等上网活动,无一例外都在使用DNS服务.*******************************************************************************    DNS的基本知识:        DNS服务器的组成        DNS域名称