

叁蓙大山:工謪、稅務、嗣發 抱歉:不回答女人的问题
题目是说可能重复的号码不超过10000,并不是说独立的号码
昨天写的,本来不想发,不过留着也没什么用
先发出来,看看大家的修改意见,以达到题目要求,特别是内存限制
如果用数组,因为原始数据最多有一百万个之多,没输入最后一个数据之前
无法判断以前的数据哪个会不会重复,所以数据都得存起来,感觉不合适!
代码运行环境,C-Free(XP)
[CODE]
#include "stdio.h"
#include "malloc.h"
#include "stdlib.h"
typedef struct node{
long tel_num; /*号码*/
char frequ_num; /*重复次数*/
struct node* next;
} *Linklist,Node;
long n;
char code[8][4]={ "ABC","DEF","GHI","JKL","MNO","PRS","TUV","WXY"};
int Sear_subcript(char ch) /*找到字符对应的数字字符*/
{
int i,j;
for(i=0;i<7;i++)
for(j=0;j<3;j++)
if(code[i][j]==ch)
return i+50;
return 0;
}
Linklist Infor_Input(void)
{
Linklist head, newp,previousp,currentp;
int j,subcript;
long i;
char ch,str[15];
head=(Linklist) malloc (sizeof(Node));
if(head==NULL)
exit(-1);
head->next=NULL;
for(i=0;i<n;i++)
{
newp=(Linklist) malloc (sizeof(Node));
if(newp==NULL)
exit(-1);
newp->next=NULL;
for(j=0;j<8;j++)
{
ch=getchar();
if(ch>='0'&&ch<='9')
str[j]=ch;
else if(subcript=Sear_subcript(ch))
str[j]=subcript;
else if(ch=='\n')
{
str[7]='\0';
newp->tel_num=atol(str); /*转化为数字*/
newp->frequ_num=1;
break;
}
else
j--;
}
if(!head->next) /*链表的一个按数字大小的前插操作*/
head->next=newp;
else
{
previousp=NULL;
currentp=head->next;
if(currentp->tel_num == newp->tel_num)
currentp->frequ_num++;
else if(currentp->tel_num > newp->tel_num)
{
newp->next=currentp;
head->next=newp;
}
else
while( currentp->tel_num < newp->tel_num)
{
previousp=currentp;
currentp=currentp->next;
if(currentp)
{
if(currentp->tel_num == newp->tel_num)
{
currentp->frequ_num++;
break;
}
if(currentp->tel_num > newp->tel_num)
{
previousp->next=newp;
newp->next=currentp;
break;
}
}
else
{
previousp->next=newp;
break;
}
}
}
}
return head;
}
void Display_result(Linklist head)
{
int flag=0;
head=head->next;
while(head)
{
if(head->frequ_num>1)
{
printf("%03ld-%04ld %d\n",head->tel_num/10000,
head->tel_num%10000,head->frequ_num);
flag=1;
}
head=head->next;
}
if(!flag)
printf("No duplication!\n");
}
void Destory_Linklist(Linklist head)
{
Linklist currentp;
while(head)
{
currentp=head;
head=head->next;
free(currentp);
}
}
int main()
{
Linklist head;
printf("n=");
scanf("%ld",&n);
fflush(stdin); /*处理掉\n*/
head=Infor_Input();
printf("\n\n");
Display_result(head);
Destory_Linklist(head);
return 0;
}
/*-----------------*
电话号码问题(VC下)
*-----------------*/
#include<stdio.h>
#include<stdlib.h> //调用ldiv()
#include<string.h> //调用memmove()
#define LPHONE 7 //电话号码的位数
char b['Z']={0, //将诸如ABC译为2,…,WXY译为9等
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,
2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,0,7,7,8,8,8,9,9,9};
char NB[1250000];//可存放1千万个不同号码
struct
{
long num;//号码本身
char dup;//复用次数
} ph[10000],*p;
int iph=0;//统计复用号码总数
//将num写入复用号码表ph[ ]
void insert(long num)
{
int i;
//以下是顺序搜索最好改成二分搜索
for(p=ph,i=0;i<iph;i++,p++)
if(num<p->num)break;
else if(num==p->num)
{ p->dup++;return; }
memmove(p+1,p,(iph-i)*sizeof(ph[0]));
p->num=num;
p->dup=2;//为何不是1?
iph++;
}
int main()
{
ldiv_t re; //这是ldiv()所要求的
int ntest=12; //测试数据有12个
char*test[ ]={//具体测试数据如下
"4873279","ITS-EASY","888-4567","3-10-10-10",
"888-GLOP","TUT-GLOP","967-11-11","310-GINO",
"F101010","888-1200","-4-8-7-3-2-7-9","487-3279",
};
unsigned char tmp,val;
int i,j,k;
long nb;
for(j=0;j<ntest;j++)
{
for(nb=k=i=0;i<LPHONE;k++)
{
sscanf(test[j]+k,"%c",&tmp);
if(tmp=='-')continue;
nb=nb*10+b[tmp];
++i;
}
re=ldiv(nb,8);//效果re.rem=nb%8和re.quot=nb/8
val=1;val<<=re.rem;//效果val=pow(2,re.rem)
tmp=NB[re.quot];
if(tmp+val==(tmp|val)) //这是得意之笔
NB[re.quot]|=val;//若是迄今未见复用的号码,相应位置1
else insert(nb);
}
//效果验证:
if(iph==0)
printf("No duplication\n");
else
for(p=ph,i=0;i<iph;i++,p++)
{ re=ldiv(p->num,10000);
printf("%d: %03d-%04d %d\n",i+1,re.quot,re.rem,p->dup);
}
return 0;
}
[此贴子已经被作者于2006-5-30 9:25:43编辑过]