nyoj 163 phonelist 字典树(2)

来源:互联网 发布:软件外包网 编辑:程序博客网 时间:2024/06/05 09:00

这是我做的字典树第二题,纠结了几天,终于做出来了,感觉真爽大笑

主题思想:把每个经过的结点进行标记,没走之前都把flag标记为0,走过的标记为1,一串电话号的末尾标记为2;

举个例子 123和12

1.先插123;然后再插12,当插到最后2时,发现2已经被标记为1了,说明已经走过,即已经存在比他更长的有公共前缀短的电话号,此时说明电话薄不能建立,把判断能否建立的变量Flag置为1,;

2.先插12;在插到2时发现,flag为2,说明已经出现过比他短的且有公共前缀的电话号,不能建立(只要在插入的途中遇到2就说明不能建立)

#include<stdio.h>#include<string.h>#include<stdlib.h>int Flag;//标记电话薄是否能建立,如果可以为0,否则为1typedef struct node{node *next[10];int flag;//用来标记,初始为0,如果走过标记为1,末尾标记为2}node;node *root;node *newset(){node *p=(node *)malloc(sizeof(node));//动态分配内存for(int i=0;i<10;i++){p->next[i]=NULL; }     p->flag=0;//初始为0return p;}void insert(char *a){node *p;p=root;  int k=strlen(a);  for(int i=0;i<k;i++)  {   if(p->next[a[i]-48]==NULL)//建立结点p->next[a[i]-48]=newset();    p=p->next[a[i]-48];  if(p->flag==0&&i<k-1) p->flag=1;//经过就标记,但不标记最后一个   if(p->flag==2) {Flag=1;}//如果途中遇到2,说明不能建立,Flag为1 if(i==k-1)//最后一个   {        if(p->flag==1||p->flag==2)//末尾如果走过,Flag为1{ p->flag=2;                  Flag=1;}if(p->flag==0) p->flag=2;//如果没走过,把末尾标记为2   }  } }void clear(node *t)//清空{if(t!=NULL){for(int i=0;i<10;i++)clear(t->next[i]);free(t);//释放内存}}int main(){    int n,m;char a[12];scanf("%d",&n);while(n--){root=newset();//此处卡了好久,根结点一定要分配内存scanf("%d",&m);Flag=0;while(m--){scanf("%s",a);insert(a);}if(Flag==0) printf("YES\n");              else printf("NO\n");clear(root);//清空}return 0;}


原创粉丝点击