• C++实现将字符串循环左移n个位置


    /**
     * @file 020_move_string.c
     * @author dinghuaneng
     * @date 2011.06.22
     * @brief 将字符串进行向左旋转,即循环左移的算法实现。
     *        最后那种方法在时间和空间上都很高效,且代码简短,很难出错。
     *        最节约空间和时间的方法来源:《编程珠玑》
     * @defgroup move_string
     * @{
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    /*********************** 最节约时间的方法 ************************/
    /**
     * @brief 将字符串向左旋转n个位置
     * @param      str  待旋转的字符串
     * @param[in]  mov  需要旋转的数量
     * @return 无
     */
    void move_string_left(char *str, int mov)
    {
        if (NULL == str || mov <= 0)
            return;
        char tmp[mov];
        int i;
        int len = strlen(str);
        if (len == 0)
            return;
        mov %= len;
        if (mov == 0)
            return;
        for (i = 0; i < sizeof tmp; i++)
            tmp[i] = str[i];
        tmp[i] = '\0';
        for (i = 0; i < len-mov; i++)
            str[i] = str[i+mov];
        for (; i < len; i++)
            str[i] = tmp[i-(len-mov)];
    }

    /**
     * @brief 将字符串向右旋转n个位置
     * @param      str  待旋转的字符串
     * @param[in]  mov  需要旋转的数量
     * @return 无
     */
    void move_string_right(char *str, int mov)
    {
        if (NULL == str || mov <= 0)
            return;
        char tmp[mov];
        int i;
        int len = strlen(str);
        if (len == 0)
            return;
        mov %= len;
        if (mov == 0)
            return;
        for (i = len - mov; i < len; i++) {
            tmp[i-(len-mov)] = str[i];
        }
        tmp[i-(len-mov)] = '\0';
        for (i = len - 1; i >= mov; i--) {
            str[i] = str[i-mov];
        }
        for (; i >= 0; i--)
            str[i] = tmp[i];
    }
    /*********************** 最节约时间的方法 ************************/

    /*********************** 最节约空间的方法 ************************/
    /**
     * @brief 将字符串向左旋转1个位置
     * @param      str  待旋转的字符串
     * @param[in]  mov  需要旋转的数量
     * @return 无
     */
    void move_string_one_left(char *str)
    {
        if (NULL == str)
            return;
        int  len = strlen(str);
        int  i;
        if (len == 0)
            return;
        char tmp = str[0];
        for (i=0; i<len-1; i++) {
            str[i] = str[i+1];
        }
        str[i] = tmp;
    }

    /**
     * @brief 将字符串向右旋转1个位置
     * @param      str  待旋转的字符串
     * @param[in]  mov  需要旋转的数量
     * @return 无
     */
    void move_string_one_right(char *str)
    {
        if (NULL == str)
            return;
        int  len = strlen(str);
        if (len == 0)
            return;
        char tmp = str[len-1];
        int  i;
        for (i=len-1; i>0; i--) {
            str[i] = str[i-1];
        }
        str[i] = tmp;
    }
    /*********************** 最节约空间的方法 ************************/

    /*********************** 最节约空间和时间的方法之一 ************************/
    /**
     * @brief 返回数值i和j的最大公约数
     * @return 正确返回最大公约数,参数有问题返回-1
     */
    int gcd(int i, int j)
    {
        if (i<=0 || j<=0)
            return -1;
        while (i != j) {
            if (i > j)
                i -= j;
            else
                j -= i;
        }
        return i;
    }

    /**
     * @brief 将字符串向左旋转n个位置
     * @param      str  待旋转的字符串
     * @param[in]  mov  需要旋转的数量
     * @return 无
     */
    void move_string_fast_left(char *str, int mov)
    {
        if (NULL == str || mov <= 0)
            return;
        int len = strlen(str);
        char tmp;
        if (!mov)
            return;
        mov %= len;
        if (!mov)
            return;
        int i, j, k;
        int g_cd = gcd(mov, len);
        for (i=0; i<g_cd; i++) {
            tmp = str[i];
            j = i;
            while (1) {
                k = j + mov;
                if (k >= len)
                    k -= len;
                if (k == i)
                    break;
                str[j] = str[k];
                j = k;
            }
            str[j] = tmp;
        }
    }

    /**
     * @brief 将字符串向右旋转n个位置
     * @param      str  待旋转的字符串
     * @param[in]  mov  需要旋转的数量
     * @return 无
     */
    void move_string_fast_right(char *str, int mov)
    {
        if (NULL == str || mov <= 0)
            return;
        int len = strlen(str);
        if (!mov)
            return;
        mov %= len; // 修移动次数
        if (!mov)
            return;
        mov = len - mov;
        move_string_left(str, mov);
    }
    /*********************** 最节约空间和时间的方法之一 ************************/

    /*********************** 最节约空间和时间的方法之二 ************************/
    /**
     *  @brief 交换字符串str中的从pos1开始和从pos2开始长度为num的两部分元素。
     *         注意防止内存越界!
     *  @param      str  待交换部分字符的字符串
     *  @param[in]  pos1 第一部分起始位置
     *  @param[in]  pos2 第二部分起始位置
     *  @param[in]  num  要交换的字符数量Architexa的反编译和破解
     */
    void swap_string(char *str, int pos1, int pos2, int num)
    {
        char *str1 = str + pos1;
        char *str2 = str + pos2;
        int i;
           char tmp;
        for (i=0; i<num; i++) {
            tmp   = *str1;
            *str1 = *str2;
            *str2 = tmp;
            str1++;
            str2++;
        }
    }

    /**
     * @brief 用交换元素的方法进行向左旋转(循环左移)
     * @param      str  待旋转的字符串
     * @param[in]  mov  需要旋转的数量
     * @return 无
     */
    void move_string_swap_left(char *str, int mov)
    {
        if (NULL == str || mov <= 0)
            return;
        int len = strlen(str);
        if (!mov)
            return;
        mov %= len; // 修移动次数
        if (!mov)
            return;
        int i = mov;
        int j = len - mov;
        while (i != j) {
            if (i > j) {
                swap_string(str, mov-i, mov, j);
                i -= j;
            }
            else {
                swap_string(str, mov - i, mov - i + j, i);
                j -= i;
            }
        }
        swap_string(str, mov-i, mov, i);
    }
    /*********************** 最节约空间和时间的方法之二 ************************/

    /*********************** 最节约空间和时间的方法之三 ************************/
    /**
     * @brief 将字符串str中从start开始至end结束的字符进行逆转
     * @param     str  待逆转部分字符的字符串
     * @param[in] start  开始的位置
     * @param[in] end    结束的位置
     * @return 无
     */
    void reverse(char *str, int start, int end)
    {
        char *pos1 = str + start;
        char *pos2 = str + end;
        char  tmp;
        while (pos1 < pos2) {
            tmp   = *pos1;
            *pos1 = *pos2;
            *pos2 = tmp;
            pos1++;
            pos2--;
        }
    }

    /**
     * @brief  利用逆转的方法对字符串进行向左旋转(循环左移)
     * @param      str  待旋转的字符串
     * @param[in]  mov  需要旋转的数量
     * @return 无
     */
    void move_string_reverse_left(char *str, int mov)
    {
        if (NULL == str || mov <= 0)
            return;
        int len = strlen(str);
        if (!mov)
            return;
        mov %= len; // 修移动次数
        if (!mov)
            return;
        reverse(str, 0, mov-1);
        reverse(str, mov, len-1);
        reverse(str, 0, len-1);
    }
    /*********************** 最节约空间和时间的方法之三 ************************/
    /** @} */

    #if 1
    int main(int argc, char **argv)
    {
        char str[] = "Hello World!";
        int  n = atoi(argv[1]);
        int  i;
        move_string_reverse_left(str, n);
        printf("%s\n", str);
        return 0;
    }
    #endif

  • 相关阅读:
    【转】数据安全保护之访问控制技术
    WebRTC介绍及简单应用
    【转】Weblogic的集群
    【转载】桥接Microsoft Word和浏览器
    http Content-type对照表
    CentOS7.1下JDK+Tomcat应用环境搭建
    关于silverlight5 打印功能收集
    【转】2014年25款最好的jQuery插件
    lesson11
    lesson 9
  • 原文地址:https://www.cnblogs.com/sky7034/p/2092045.html
Copyright © 2020-2023  润新知