| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1470 人关注过本帖, 1 人收藏
标题:用分治计数对字符串进行排序~
只看楼主 加入收藏
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
结帖率:99.25%
收藏(2)
 问题点数:0 回复次数:9 
用分治计数对字符串进行排序~
正常来说字符串排序都是通过strcmp来比较的,那能不能不以字符串为单位而是以单个字符为单位进行排序呢~

对于某字符串可以这样,先对所有字符串的第一个字符进行排序,相等的就分成一组,那一组里面再对第二个字符进行排序……直到所有字符串都能独立分成一组(包括全等)为止~

那用分治法就是把那一行字符都相等的分成一组,剩下的部分分成另外一组,这样不断细分直到每一个字符串都是独立的一组(包括相等)为止~
就有如下代码~

不能保证说完全没有bug,但基本就是这个样子了可以看看~

程序代码:
#include<stdio.h>

typedef struct Load
{   
    const char* p;
    
    size_t index;
}Load;

void nodeMal( void** ,size_t );
void nodeFree( void** );

int comp( const void*,const void* );

char* input( char* ,size_t );

void fun( const char* [],size_t,int (*)( const void*,const void* ) );

void _sort( Load* ,size_t,size_t,int (*)( const void*,const void* ) );

int main( void )
{    
    #define __ARR_LEN( s )    \
    (sizeof (s)/sizeof (*s))
    
    char str[5][100];
    
    const char* p[__ARR_LEN(str)];
    
    size_t i;
     
    puts("Input 5 strings:");  
    for (i=0;i!=__ARR_LEN(str);++i)
    {
        input(str[i],sizeof (str));
        p[i]=str[i];
    }
    
    fun(p,__ARR_LEN(str),comp);
   
   puts("--------------------");
    for (i=0;i!=__ARR_LEN(str);++i)
        puts(p[i]);

    return 0;
    
    #undef __ARR_LEN
}

#include<stdlib.h>
#include<string.h>
#include<assert.h>

void nodeMal( void** p,size_t size )
{
    assert(p);
    
    *p=malloc(size);
    
    assert(*p);

    memset(*p,0,size);
}

void nodeFree( void** p )
{
    assert(p);
    
    free(*p);
    *p=NULL;
}

int comp( const void* p,const void* q )
{
    const char* const _p=(( Load* )p)->p;
    const char* const _q=(( Load* )q)->p;
    
    const size_t index=(( Load* )p)->index;
    
    return _p[index]-_q[index];
}

char* input( char* s,size_t size )
{
    char* p=NULL;
    fgets(s,size,stdin);
    
    if ((p=strchr(s,'\n'))!=NULL)
            *p='\0';
        else
            scanf("%*[^\n]%*c");
    
     return s;
}

void fun( const char* str[],size_t n,int (*comp)( const void*,const void* ) )
{
    Load* load=NULL;
    
    size_t i;
    
    nodeMal(( void** )&load,n*sizeof (*load));
    
    for (i=0;i!=n;++i)
    {
        load[i].p=str[i];
        load[i].index=0;
    }
    
   qsort(load,n,sizeof (*load),comp);
   
   _sort(load,0,n,comp);
   
   for (i=0;i!=n;++i)
       str[i]=load[i].p;  
    
    nodeFree(( void** )&load);
}

void _sort( Load* load,size_t low,size_t height,int (*comp)( const void*,const void* ) )
{
    if (low>=height)
        return ;

    {                
        const Load key=load[low];
        
        int flag=0;
        
        size_t i=low;
       
        for (;(i!=height)&&(comp(&key,&load[i])==0);++i)
            if (load[i].p[load[i].index])
                ++load[i].index;
            else
                flag=1;
      
        if (i-low>1)
            qsort(&load[low],i-low,sizeof (*load),comp);
     
        if (height-low<2)
          return ;
        
        if (flag==0)
            _sort(load,low,i,comp);
            
        _sort(load,i,height,comp);
    }      
}


[此贴子已经被作者于2018-5-2 22:12编辑过]

收到的鲜花
  • ehszt2018-04-27 21:08 送鲜花  1朵   附言:不错
搜索更多相关主题的帖子: str Load const char void 
2018-04-27 20:34
ehszt
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:40
帖 子:1745
专家分:3216
注 册:2015-12-2
收藏
得分:0 
不错,体现了分治法的思想。递归用的好。
2018-04-27 21:11
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 2楼 ehszt
然后看了一下(没有具体对比)意外地发现感觉和正常的strcmp的比较次数差不多,需要弄个实例看看才行~

[此贴子已经被作者于2018-4-28 05:28编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-04-27 21:14
ehszt
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:40
帖 子:1745
专家分:3216
注 册:2015-12-2
收藏
得分:0 
感觉那个已知前序和中序求后序,也用了分治法。
2018-04-27 21:23
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 4楼 ehszt
是的,就是这样~

[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-04-27 21:47
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
之后再看了一下,发现不仅是和正常的strcmp比较差不多,甚至比较次数还多了(因为递归),所以这样多少有点无语~
然后看了也并不是没有发展方向的,嗯,详细解决方案见下楼吧~

[此贴子已经被作者于2018-4-28 09:18编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-04-28 05:38
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
继续更~

之后新get到一种排序方案~
大意就是说根据字符串所有字符出现创建一个目录索引(具体点就是桶排序--不过这个桶是有目录的)

然后用合并相同的字符再进行快排,保证快排的时候没有重复的字符出现,这样可以确保每个字符在比较的时候只是遍历一次~

[此贴子已经被作者于2018-4-28 09:01编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-04-28 06:09
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
总算用了桶排序思想弄出来了,之前一楼发现bug顺便修复~先给出代码(代码有点长,但主要还是桶排序思想)~

程序代码:
#include<stdio.h>

typedef struct Load
{   
    const char* p;
    
    size_t index;
}Load;

typedef struct Load_Node
{
    Load data;
    
    struct Load_Node* next;
}Load_Node;

typedef struct Load_Head
{
    Load_Node* index[256];
    
    Load_Node* list;
    Load_Node* top;
    
}Load_Head;

void nodeMal( void** ,size_t );
void nodeFree( void** );

int comp( const void*,const void* );

char* input( char* ,size_t );

void fun( const char* [],size_t,int (*)( const void*,const void* ) );

static void _sort( Load_Head*,Load* ,size_t,size_t,int (*)( const void*,const void* ) );

static void _merge( Load_Head*,Load*,size_t,size_t,int (*)( const void*,const void* ));

static void _init_load_head( Load_Head* );

static void _set_load_head( Load_Head*,size_t );

static void _insert_load( Load_Head*,Load* );

static void _recycle_load( Load_Head*,Load* );

int main( void )
{    
    #define __ARR_LEN( s )    \
    (sizeof (s)/sizeof (*s))
    
    char str[5][100];
    
    const char* p[__ARR_LEN(str)];
    
    size_t i;
     
    puts("Input 5 strings:");  
    for (i=0;i!=__ARR_LEN(str);++i)
    {
        input(str[i],sizeof (str));
        
        p[i]=str[i];
    }
    
    fun(p,__ARR_LEN(str),comp);
   
   puts("--------------------");
    for (i=0;i!=__ARR_LEN(str);++i)
        puts(p[i]);

    return 0;
    
    #undef __ARR_LEN
}

#include<stdlib.h>
#include<string.h>
#include<assert.h>

void nodeMal( void** p,size_t size )
{
    assert(p);
    
    *p=malloc(size);
    
    assert(*p);

    memset(*p,0,size);
}

void nodeFree( void** p )
{
    assert(p);
    
    free(*p);
    *p=NULL;
}

int comp( const void* p,const void* q )
{
    const char* const _p=(( Load_Node* )p)->data.p;
    const char* const _q=(( Load_Node* )q)->data.p;
    
    const size_t index=(( Load_Node* )q)->data.index;
    
    return _p[index]-_q[index];
}

char* input( char* s,size_t size )
{
    char* p=NULL;
    fgets(s,size,stdin);
    
    if ((p=strchr(s,'\n'))!=NULL)
            *p='\0';
        else
            scanf("%*[^\n]%*c");
    
     return s;
}

void fun( const char* str[],size_t n,int (*comp)( const void*,const void* ) )
{
    Load_Head head;
    
    Load* load=NULL;
    
    size_t i;
   
    _init_load_head(&head);
    
    nodeMal(( void** )&load,n*sizeof (*load));
    
    for (i=0;i!=n;++i)
        load[i].p=str[i];
    
   _merge(&head,load,0,n,comp);
   
   _sort(&head,load,0,n,comp);
   
   for (i=0;i!=n;++i)
       str[i]=load[i].p;  
    
    nodeFree(( void** )&load);
}

static void _sort( Load_Head* head,Load* load,size_t low,size_t height,int (*comp)( const void*,const void* ) )
{
    if (low>=height)
        return ;

    {                
        Load_Node key;
        
        int flag=0;
        
        size_t i;
               
       key.data=load[low];         
       
        for (i=low;i!=height;++i)
        {
            Load_Node com_data;           
            com_data.data=load[i];
            
            if (comp(&key,&com_data)!=0)
                break;
                
            if (load[i].p[load[i].index])
                ++load[i].index;
            else
                flag=1;
        
        }
      
      if (i-low>1)
        _merge(head,load,low,i,comp);
     
        if (height-low<2)
            return ;
        
        if (flag==0)
            _sort(head,load,low,i,comp);
            
        _sort(head,load,i,height,comp);
    }      
}

static void _merge( Load_Head* head,Load* load,size_t low,size_t height,int (*comp)( const void*,const void* ))
{    
    size_t i;


 _set_load_head(head,(height-low)*sizeof (*head->list));

 
    for (i=low;i!=height;++i)
        _insert_load(head,&load[i]);
    
   {
       const size_t count=head->top-head->list;
     
       if (count>1)
           qsort(head->list,count,sizeof (*head->list),comp);
   }
      
   _recycle_load(head,&load[low]);               
}

static void _init_load_head( Load_Head* head )
{
    memset(head,0,sizeof (*head));
}

static void _set_load_head( Load_Head* head,size_t size )
{       
    nodeMal( ( void** )&head->list,size);
    
    head->top=head->list;
}

static void _insert_load( Load_Head* head,Load* load )
{
    const unsigned char ch=( const unsigned char )load->p[load->index];

    Load_Node** index=&head->index[ch];                     
    if (*index==NULL)
    {
        *index=head->top++;
        (*index)->data=*load;
    }
    else
    {
        Load_Node* node=NULL;

        nodeMal(( void** )&node,sizeof (*node));
        
        node->data=*load;
        
        node->next=(*index)->next;
        (*index)->next=node;
    }        
}

static void _recycle_load( Load_Head* head,Load* load )
{
    Load_Node* p;
    Load_Node* top=head->top;

    for (p=head->list;p!=top;++p)
    {
        head->index[( const unsigned char )p->data.p[p->data.index]]=NULL;
        
       *load=p->data;

        for (++load;p->next!=NULL;++load)
        { 
            Load_Node* k=p->next;
            Load_Node** t=&k;
            
            *load=(*t)->data;
                   
            p->next=(*t)->next;
            
            nodeFree(( void** )t);
        }
    }

 
    nodeFree(( void** )&head->list);
}


[此贴子已经被作者于2018-5-3 00:06编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-02 22:13
自学的数学
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:贵宾
威 望:46
帖 子:967
专家分:4146
注 册:2017-11-15
收藏
得分:0 
我把楼主第一层的代码运行了下,效果如图:
图片附件: 游客没有浏览图片的权限,请 登录注册

这个是不是楼主代码要达到的要求呢?好象还有点不合吧。
不然是我理解错了??
2018-05-02 22:32
九转星河
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:长长久久
等 级:贵宾
威 望:52
帖 子:5023
专家分:14003
注 册:2016-10-22
收藏
得分:0 
回复 9楼 自学的数学
比较字符串大小难道不是这个么,看上去正常~

PS:8楼bug已修正~

[此贴子已经被作者于2018-5-4 02:17编辑过]


[code]/*~个性签名:bug是什么意思?bug是看上去没有可能的东西实际上是有可能做到的 就是这样~2018-08-08更~*/[/code]
2018-05-03 00:07
快速回复:用分治计数对字符串进行排序~
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.042152 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved