C++复合数据类型应用案例

一.翻转数组

翻转数组就是要把数组中的元素的顺序反过来,比如一个数组{1, 2, 3, 4, 5, 6, 7, 8, 9},翻转之后就是{9, 8, 7, 6, 5, 4, 3, 2, 1}

1.思路一:

另外创建数组,反向把元素填入新创建的数组中

数组是将元素按照顺序依次存放的,长度固定,所以如果想要让数组“翻转”的话,一种最简单的思路就是直接创建一个相同长度的新数组,然后遍历所有元素,从末尾开始依次反向填入就可以了

#include"iostream"
using namespace std;

int main(){
    const int len = 10;
    int arr[len] = {0, 1, 2, 3, 4, 5, 6 ,7, 8, 9};
    // 答案数组
    int ans[len];
    for (int i = 0; i < len; i++) {
        ans[len - i - 1] = arr[i];
    }

    for (int num : ans) {
        cout << num << "\t";
    }
};

2.思路二:

利用双指针,直接完成基于原数组的翻转

#include"iostream"
using namespace std;

int main(){
    const int len = 10;
    int arr[len] = {0, 1, 2, 3, 4, 5, 6 ,7, 8, 9};

    // 利用双指针完成基于原数组的翻转
    int head = 0, tail = len - 1;

    while (head < tail) {
        int temp = arr[head];
        arr[head] = arr[tail];
        arr[tail] = temp;
        tail--;
        head++;
    }
    
    for (int num : arr) {
        cout << num << "\t";
    }
};

二.检验幻方

幻方是数学上的一个问题,它让一组不同的数组构成一个方阵,并且每行、每列、每个对角线的所有数之和相等,比如最简单的三阶幻方就是把1~9的数字填到九宫格里,要求横看、竖看、斜看的和都是15

我们可以给定一个n*n的矩阵,也就是二维数组,然后判断它是否是一个幻方

#include"iostream"
using namespace std;

int main(){
    const int n = 3;
    int arr[n][n] = {
            {4, 9, 2},
            {3, 5, 7},
            {8, 1, 6}
    };

    // 计算目标和
    int target = (1 + n * n) * n / 2;
    bool judge = true;

    // 还可以使用双重循环同时检验每一行和每一列是否满足条件
    /*
    for (int i = 0; i < n; i++) {
        int row = 0, line = 0;
        for (int j = 0; j < n; j++) {
            row += arr[i][j];
            line += arr[j][i];
        }
        
        if (row != target || line != target) {
            judge = false;
            break;
        }
    }
     */
    
    // 检查每一行都是否满足条件
    for (int i = 0; i < n; i++) {
        int sum = 0;
        for (int j = 0; j < n; j++) {
            sum += arr[i][j];
        }

        if (sum != target) {
            judge = false;
            break;
        }
    }

    // 检查每一列是否满足条件
    for (int i = 0; i < n; i++) {
        int sum = 0;
        for (int j = 0; j < n; j++) {
            sum += arr[j][i];
        }

        if (sum != target) {
            judge = false;
            break;
        }
    }

    // 检查对角线位置是否满足条件
    int leftToright = 0, rightToleft = 0;
    for (int i = 0; i < n; i++) {
        leftToright += arr[i][i];
        rightToleft += arr[i][n - 1 - i];
    }

    if (leftToright != target || rightToleft != target) {
        judge = false;
    }

    // 输出结果
    cout << "Given matrix" << (judge ? " is " : " isn't ") << n << " order magic square";
};

三.大整数相加

在我们的实际应用中可能会遇到非常大的整数,甚至超过long long的范围,这时候就需要用字符串对数据进行保存,然后进行计算

最简单的需求就是“大整数相加”,也就是给定两个字符串形式的非负大整数计算它们的和

我们的思路是把字符串按每个字符一一拆开,相当于遍历整数上的每一个数位,然后通过“乘10叠加”的方式将它们整合起来,也就是我们经常用的“竖式加法”

#include"iostream"
using namespace std;

int main(){
    string num1 = "12564512567548545532464874545623145";
    string num2 = "21542135442465214534212456652344154";

    // 答案字符串
    string ans;

    int len1 = num1.size() - 1;
    int len2 = num2.size() - 1;

    // 是否进位
    int carry = 0;

    // 循环遍历,两数对齐进行相加
    while (len1 >= 0 || len2 >= 0) {
        // 两个数是否遍历完,若已完成则补0
        int x = (len1 >= 0) ? (num1[len1] - '0') : 0;
        int y = (len2 >= 0) ? (num2[len2] - '0') : 0;

        int sum = x + y + carry;
        carry = sum / 10;

        ans += (sum % 10 + '0');

        len1--;
        len2--;
    }

    // 还需要对结果进行翻转
    int i = 0, j = ans.size() - 1;
    while (i < j) {
        char temp = ans[i];
        ans[i] = ans[j];
        ans[j] = temp;

        i++;
        j--;
    }

    cout << num1 << " + " << num2 << " = " << ans;
};

四.旋转图像

旋转图像的需求在图片处理的过程中非常常见,我们知道对于计算机而言,图像就是一组像素点的集合,所以图像旋转的问题本质上就是一个二维数组的旋转问题

因此我们可以给定一个二维数组表示一个图像,然后对其进行旋转

#include"iostream"
using namespace std;

int main(){
    const int n = 4;
    // 将矩阵顺时针翻转90度
    int arr[n][n] = {
            {5, 1, 9, 11},
            {2, 4, 8, 10},
            {13, 3, 6 , 7},
            {15, 14, 12, 16}
    };

    // 以对角线为对称轴,两边元素进行互换
    for (int i = 0; i < n; i++) {
        for (int j = 0; j <= i; j++) {
            int temp = arr[i][j];
            arr[i][j] = arr[j][i];
            arr[j][i] = temp;
        }
    }

    // 对每一行都进行前后翻转
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n / 2; j++) {
            int temp = arr[i][j];
            arr[i][j] = arr[i][n - j - 1];
            arr[i][n - j - 1] = temp;
        }
    }

    for (int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            cout << arr[i][j] << "\t";
        }
        cout << endl;
    }
};

五.旋转链表

链表是一种常见的数据结构,对于数组来说,我们可以通过下标访问每个元素,也能够做到如果想要翻转一个数组,只需要不停地把头尾元素互换即可

而链表并没有“下标”,所以想要访问元素的话就只能依次遍历,如果想要翻转一个链表,关键在于“next”指针需要反向

#include"iostream"
using namespace std;

struct ListNode {
    int value;
    ListNode* next;
};

int main(){
    ListNode p5 = {5, nullptr};
    ListNode p4 = {4, &p5};
    ListNode p3 = {3, &p4};
    ListNode p2 = {2, &p3};
    ListNode p1 = {1, &p2};

    ListNode* list = &p1;

    ListNode* np = list;
    while(np) {
        cout << (*np).value << "->";
        np = (*np).next;
    }
    cout << "NULL" << endl;

    // 为了进行链表的翻转,我们需要定义两个指针,一个指向当前遍历的节点,另一个指向之前的节点
    ListNode* curr = list;
    ListNode* prev = nullptr;

    while (curr) {
        ListNode* temp = (*curr).next;
        (*curr).next = prev;
        prev = curr;
        curr = temp;
    }

    ListNode* newList = prev;
    np = newList;
    while(np) {
        cout << (*np).value << "->";
        np = (*np).next;
    }
    cout << "NULL" << endl;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值