字符串的几个算法

  1.字符串旋转: a b c d --> d c b a;

结合数据结构我用栈实现,因为这个过程就是进栈与出栈。但是如果单纯的字符串颠倒就不用这么麻烦直接首尾对调就可以了

//字符串翻转
void StrReverse(char* str,int start,int end)
{
    char t;
    while(start<end){
        t = str[start];
        str[start++] = str[end];
        str[end--] = t;
    }
}

      2.复杂点"I am a engineer!" --> "engineer! a am I"
这里是以单词为节点的颠倒,第一步是分割单词,第二步还是翻转,只不过这次翻转不能按照上面的方法来了。利用栈可以解决这个问题。

首先贴出栈的代码,以前已经实现过,不过这次添加了其他东西

int InitStack(Stack* q)
{
    q->bottom = q->top = (Stack_Data*)malloc(INITSIZE*sizeof(Stack_Data));
    if(!q->bottom)return -1;
    q->stack_size = INITSIZE;
    return 0;
}

//进栈
int Push(Stack* q,Stack_Data data)
{
    if(q->top - q->bottom >= q->stack_size){
        q->bottom = (Stack_Data*)realloc(q->bottom,sizeof(Stack_Data)*(q->stack_size+INCREAMENT));
        if(!q->bottom)return -1;
        q->top = q->bottom + q->stack_size;
        q->stack_size += INCREAMENT;
        printf("栈空间不足,增加空间\r\n");
    }
    *(q->top) = data;
    (q->top)++;
    return 0;
}

//出栈
int Pop(Stack* q,Stack_Data* data)
{
    //判断栈空
    if(q->bottom == q->top)return -1;
    (q->top)--;
    *data = *(q->top);
    return 0;
}
View Code

这里是基本的初始化与进栈出栈操作,但是注意定义的节点结构体

typedef struct{
    char a;
    int i;
    char str[20];//预留20个空间,保存字符串
}Stack_Data;

预留了字节数组保存字符串。如果单词大小超过20字节就会出错。准备了栈,还需要实现split函数

//字符串截断,返回字段数目
//regex:分割字符标志
//cp:保存分割的字符
//返回分割出的字符个数
int StrSplit(char* str,char regex,char* cp[])
{
    int i=0;
    int offset = 0;
    while(*str!='\0'){
        if(*str == regex){
            if(*(str-1) != regex){ //防止连续出现多个分割字符
                i++;
            }
            offset = 0;
        }else{
            //printf("%c",*str);
            *(cp[i]+offset) = *str;
            offset++;
        }
        str++;
    }
    return i+1;
}

以上准备工作结束,可以完成单词翻转函数:

//单词翻转
//str:翻转的字符串
//collect:保存翻转单词后的数组
int WordReverse(char* str,char* collect[])
{
    char* wordArr[10];//零时保存单词,预留10个,如果要完备算法可以继续添加
    Stack Q;  //设定栈
    Stack_Data stack_temp;
    int i,max;
    for(i=0;i<10;i++){ //分配堆空间保存单词
        wordArr[i] = (char*)malloc(20*sizeof(char));
        if(wordArr[i]){
            memset(wordArr[i],0,20*sizeof(char));//记得初始化堆空间 
        }else{
            return -1;
        }
    }
    max = StrSplit(str,' ',wordArr);//分割单词,保存分割出的单词个数
    InitStack(&Q);//初始化栈
    for(i=0;i<max;i++){//进栈
        strcpy(stack_temp.str,wordArr[i]);//复制单词到栈节点
        Push(&Q,stack_temp);//进栈
    }
    for(i=0;i<max;i++){
        Pop(&Q,&stack_temp);//出栈
        strcpy(collect[i],stack_temp.str);//保存单词
        //printf("%s ",stack_temp.str);
    }
    return 0;
}

验证代码:

int main(int argc, char *argv[]) {
    char* str = "i am a engineer!";
    char* strArr[10];
    int i;
    for(i=0;i<10;i++){
        strArr[i] = (char*)malloc(20*sizeof(char));
        memset(strArr[i],0,10);
    }
    WordReverse(str,strArr);

    for(i=0;i<10;i++){
        if(*strArr[i] == 0)break;
        printf("%s ",strArr[i]);
    }
    printf("\r\n");
    system("pause");
    return 0;
}

运行结果:

  3. 将abcdefg --> efgabcd 就是将前N个字符放到字符的结尾。

可以利用"三步翻转法":a. abcd  --> dcba;

              b. efg     --> gfe;

          c. dcbagfe -->efgabcd;  将上面翻转过的字符串合并在翻转就是要的结果

posted @ 2016-10-21 10:54  麦哈顿博士  阅读(213)  评论(0编辑  收藏  举报