常见任务中的双重while循环的结构

简介: 常见任务中的双重while循环的结构

重组数组问题可以表述为

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。

核心代码如下

void reorder(int *arr, int len)
{
    if (arr == nullptr || len <= 0)
        return;
    int *bgn = arr;
    int *end = arr + len - 1;
    while (bgn < end)
    {
        //while (*bgn % 2 == 1) 
        while (*bgn & 0x1)
            bgn ++;
        //while (*end % 2 == 0)
        while (!(*end & 0x1))
            end --;
        if (bgn < end){
            int tmp = *bgn;
            *bgn = *end;
            *end = tmp;
            bgn ++;
            end --;
        }
    }
}

在编写代码的时候,会发现与快排的代码比较相似:同样是两个指针,同样是while循环里有while循环。而快排的核心代码可能更复杂一些,因为还涉及到递归。于是将快排的核心部分找出来研究:

int sort(int *data, int left, int right){
    if(left >= right) return 0;
    int i = left;
    int j = right;
    int key = data[i];
    while(i < j){
        //每次大循环内可能同时有i++和j--,如果二层循环不加i < j,可能会导致i > j?(猜想),经测试,不加i < j,结果一样 
        //while(i < j && key < data[j]){
        while(key < data[j]){//后面的值比基准值大就正常移动,一旦碰到比基准值小的就停下
            j--;//从后往前移动
        }
        data[i] = data[j];//将小于基准的值放到前面
        //while(i < j && key >= data[i]){
        while(key >= data[i]){//基准值比前面的值小就正常移动,一旦碰到比基准值大的就停下
            i++;//从前往后移动 
        }
        data[j] = data[i];//将大于基准的值放在后面,j的位置是刚才从后往前移动时小于基准值的位置,已经被挪到前面
    }
    data[j] = key;//当i==j时,循环结束,此时的位置i==j即为基准值应该放置的位置。 
    sort(data, left, i-1);//排列基准位置左边的序列
    sort(data, i+1, right);//排列基准位置右边的序列
}

其实重组数组问题,也是一种排序。可以归为特殊的排序问题,所以在实现上跟快排有相似的代码组织结构。

由此我们可以抽象出一个模型,使用以下逻辑:

排序函数funtion()

  1. 准备工作:将两个指针或索引分别对应数组的头尾。
  2. 循环1,前面的指针不超过后面的指针。
    a. 循环2a,以某种条件移动头指针。
    b. 循环2b,以某种条件移动尾指针。
    c. 移动后的指针满足排序条件,交换两个指针对应的数值。
  3. 结束,或递归调用此过程。

还有一个比较两个压缩字符串有多少相同字符的问题,结构类似,一并贴上。

#include <stdio.h>
// str1 = 2a3b5c2d
// str2 = 3c2b4d3c
int compare(char* str1, char* str2){
    int n1 = 0, n2 = 0, n, count = 0;
    int c1 = 0, c2 = 0;
    char *p1 = str1, *p2 = str2;
    while (*p1 != '\0' || *p2 != '\0'){
        if (n1 == 0){
            while (*p1 >= '0' && *p1 <= '9'){
                n1 = n1*10 + (*p1 - '0');
                p1++;
            }
            c1 = *p++;
        }
        if (n2 == 0){
            while (*p2 >= '0' && *p2 <= '9'){
                n2 = n2*10 + (*p2 - '0');
                p2++;
            }
            c2 = *p2++;
        }
        n = n1 < n2 ? n1 : n2;
        if (c1 == c2) {
            count += n;
        }
        n1 -= n;
        n2 -= n;
    }
    return count;
}
int main()
{
    printf("%d\n",compare("2a3b5c2d","3c2b4d3c"));
    printf("%d\n",compare("5a","1c1b1d1c1a"));
}

将以上三个问题研究完,相信你应该会对这一类排序问题有比较深入的了解,并能够熟练使用双重while循环结构。

相关文章
|
Java Linux Android开发
java 对PDF的操作(生成,转换,转图片,转base64等)
java 对PDF的操作(生成,转换,转图片,转base64等)
4859 0
|
运维 监控 负载均衡
如何构建高可用的系统基础架构
【8月更文挑战第15天】构建高可用的系统基础架构是一个复杂而系统的工程,需要综合考虑设计原则、关键技术和实践策略等多个方面。通过冗余设计、分布式架构、自动化与智能化等技术的运用,可以显著提升系统的可用性和稳定性。同时,加强运维团队的能力建设和制定完善的高可用性策略也是确保系统高可用性的重要保障。希望本文能为读者在构建高可用系统时提供有益的参考和借鉴。
|
9月前
|
机器学习/深度学习 自然语言处理 搜索推荐
探秘 DeepSeek R1 模型:跨越多领域的科技奇迹,引领智能应用新浪潮
探秘 DeepSeek R1 模型:跨越多领域的科技奇迹,引领智能应用新浪潮
|
存储 监控 安全
Awk 在局域网电脑屏幕监控软件中的数据筛选
在数字化办公环境中, 局域网电脑屏幕监控软件对保障企业信息安全至关重要。Awk作为文本处理工具, 在数据筛选中发挥关键作用。示例代码展示了如何筛选特定进程数据、计算特定时间段内的活动时长以及筛选特定网站的访问记录。通过这些筛选, 可以有效监控员工行为, 支持网络管理并加强安全策略。结合其他工具和技术, 如数据库系统, 可进一步提升筛选效果和灵活性, 生成详细报告和统计信息, 从而提高工作效率和数据安全性。
114 5
|
Java API
JSP 教程 之 JSP JavaBean 1
**JSP JavaBean 技术概览:** JavaBean遵循特定规范的Java类,具备默认无参构造器、实现Serializable接口以支持序列化。核心特性包括可读写的属性及对应的getter/setter方法。属性可通过getXXX()和setXXX()访问,如getMyName()和setMyName()对应属性myName。只读属性只有getter,只写属性只有setter。
86 0
|
弹性计算 运维 Kubernetes
架构设计:物理部署图
部署图描述的是系统运行时的结构,展示了硬件的配置及其软件如何部署到网络结构中。一个系统模型只有一个部署图,部署图通常用来帮助理解分布式系统。 综上所述:物理部署图更多地是以运维的视角描绘运行时的系统的网络与部署结构。
4762 0
|
关系型数据库 MySQL 数据安全/隐私保护
系统错误:找不到mvcp120d.dll,无法继续执行代码
系统错误:找不到mvcp120d.dll,无法继续执行代码
101 0
|
JSON JavaScript 数据格式
Vue前后台数据交互实例演示,使用axios传递json字符串、数组
Vue前后台数据交互实例演示,使用axios传递json字符串、数组
699 0
|
机器学习/深度学习 数据采集 人工智能
基线提升至96.45%:2022 司法杯犯罪事实实体识别+数据蒸馏+主动学习
5.基线提升至96.45%:2022 司法杯犯罪事实实体识别+数据蒸馏+主动学习
基线提升至96.45%:2022 司法杯犯罪事实实体识别+数据蒸馏+主动学习
|
存储 SQL 关系型数据库
第九章《事务》
第九章《事务》
第九章《事务》