第七章 类、结构体、指针与引用

news2025/1/10 23:31:45

目录

  • 1.基础知识
  • 2.练习题
    • 2.1 斐波那契数列
    • 2.2 替换空格
    • 2.3 求1+2+…+n
      • 2.3.1 方法一:
      • 2.3.2 方法二:
    • 2.4 在O(1)时间删除链表结点
    • 2.5 合并两个排序的链表
    • 2.6 左旋转字符串
    • 2.7 把字符串转换成整数
    • 2.8 反转链表
    • 2.9 两个链表的第一个公共结点
    • 2.10 删除链表中重复的节点

1.基础知识

1.1 机器是不需要类的,类的出现是为了让人更好理解;
1.2 函数结束{}后面没有;,类结束{}后面有;
1.3 类和结构体差不多,数学组合定义成结构体,大型的、复杂的定义成类
1.4 类不写private,默认是私有的;结构体不写public,默认是共有的
1.5 普通类的模板

#include <iostream>
#include <string>
using namespace std;

class Person
{
    private:
        int age, height;
        double money;
        string books[100];
        
    public:
        string name;
        
        void say()
        {
            cout << "I am " << name << endl;
        }
        
        int get_age()
        {
            return age;
        }
        
        void add_money(double x)
        {
            money += x;
        }
    
};

int main()
{
    Person c;
    c.name = "dwz";
    
    cout << c.get_age() << endl;
    c.add_money(10000000000);
    
    return 0;
}

1.6 构造函数的类
普通写法

#include <iostream>
using namespace std;

struct Person
{
    int age, height;
    double money;
    
    Person() {}
    
    Person(int _age, int _height, double _money)
    {
        age = _age;
        height = _height;
        money = _money;
    }
};

int main()
{
    Person p(18, 180, 1000);
    cout << p.age << endl;
    cout << p.height << endl;
    cout << p.money << endl;
    
    return 0;
}

快速运行版本

#include <iostream>
using namespace std;

struct Person
{
    int age, height;
    double money;
    
    Person() {}
    
    Person(int _age, int _height, double _money) : age(_age), height(_height), money(_money)
    {}
};

int main()
{
    Person p(18, 180, 1000);
    cout << p.age << endl;
    cout << p.height << endl;
    cout << p.money << endl;
    
    return 0;
}

1.7 内存可简单认为栈和堆。栈是从上往下生长,堆是从下往上生长。栈里面放局部变量,函数等等,堆里面放全局变量等等。

#include <iostream>
using namespace std;
int main()
{
    
    char s = 'a';
    // void * 是无类型指针
    // & 是取变量地址的运算符
    // (类型)为强制转换类型
    // (void *) &变量,就是把变量的地址转换为无类型指针
    cout << (void*)&s << endl;
    return 0;  
}

1.8 数组名也可以做看作指针,数组长度有保存下来

#include <iostream>
using namespace std;

int main()
{
    int a[5] = {4, 7, 9, 2};
    int* p = &a[1];
    int* q = &a[3];
    cout << q - p << endl;
    
    return 0;
}
//使用循环输出数组的连续地址
#include <iostream>
using namespace std;

int main()
{
    int c[10] = {0,1,2,3,4,5};
    for(int i = 0; i < 5; i ++)
        cout << (void*) &c[i] << endl;
    return 0;
}

1.9 c++中别名,地址同一个
1.10 成员变量调用,普通变量使用点,指针使用箭头。一般头结点指的是第一个节点的地址
1.11 使用结构体构造链表,遍历链表

#include <iostream>
using namespace std;

struct Node
{
    int val;
    Node* next;
    
    Node(int _val): val(_val), next(NULL) {}
};
int main()
{
    Node* p = new Node(1);//加new返回的是地址,不加new是创建了这个类型的数据
    Node* q = new Node(2);
    Node* o = new Node(3);
    
    Node* head = p;
    p->next = q;
    q->next = o;
    
    // 链表的遍历方式
    for(Node* i = head; i; i = i->next)
        cout << i->val << endl;
    
    return 0;

}

1.12 插入节点到首位置,头节点存储的是第一个地址

#include <iostream>
using namespace std;
struct Node
{
    int val;
    Node* next;
    Node (int _val): val(_val), next(NULL){};
};
int main()
{
    Node* o = new Node(1);
    Node* p = new Node(2);
    Node* q = new Node(3);
    
    Node* head = o;
    o->next = p;
    p->next = q;
    
    for(Node* i = head; i; i = i->next)
        cout << i->val << endl;
        
    // 插入节点,置于头指针
    Node* x = new Node(4);
    x->next = o;
    head = x;
    
    for(Node* i = head; i; i = i->next)
        cout << i->val << endl;

    
    return 0;
}

1.13 链表的删除节点不是传统意义上的真删除,而是将待删除的节点跳过。步骤是当前节点要找到上一个节点,然后将当前节点的上一节点指向当前节点的下一节点。

#include <iostream>
using namespace std;
struct Node
{
    int val;
    Node* next;
    Node (int _val): val(_val), next(NULL){};
};
int main()
{
    Node* o = new Node(1);
    Node* p = new Node(2);
    Node* q = new Node(3);
    
    Node* head = o;
    o->next = p;
    p->next = q;
   
    /*
    for(Node* i = head; i; i = i->next)
        cout << i->val << endl;
    */
    
    // 插入节点,置于头指针
    Node* x = new Node(4);
    x->next = o;
    head = x;
    
    // 删除值为1的节点
    head->next = head->next->next;
    
    for(Node* i = head; i; i = i->next)
        cout << i->val << endl;

    
    return 0;
}

2.练习题

2.1 斐波那契数列

输入一个整数 n
,求斐波那契数列的第 n
项。

假定从 0
开始,第 0
项为 0

数据范围
0≤n≤39
样例
输入整数 n=5

返回 5

class Solution {
public:
    int Fibonacci(int n) {
        if(n <= 1) return n;
        else return Fibonacci(n - 1) + Fibonacci(n - 2);
    }
};

2.2 替换空格

请实现一个函数,把字符串中的每个空格替换成"%20"。

数据范围
0≤
输入字符串的长度 ≤1000

注意输出字符串的长度可能大于 1000

样例
输入:“We are happy.”

输出:“We%20are%20happy.”

class Solution {
public:
    string replaceSpaces(string &str) {
        string new_str = "";
        for(auto i : str)
        {
            if(i == ' ') new_str += "%20";
            else new_str += i;
        }
        return new_str;
    }
};

2.3 求1+2+…+n

求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句 (A?B:C)。

数据范围
1≤n≤50000。

样例
输入:10

输出:55

2.3.1 方法一:

思路:根据题意很多方法不能使用, 只能用递归。但是递归在最后一步,需要写if条件停止。为了解决这个问题,使用条件表达式短路。使用且的时候,第一个条件为假的话,直接跳过第二个条件的判断。这个特性就可以作为截止条件。

class Solution {
public:
    int getSum(int n) {
        int tmp = n;
        n > 0 && (tmp += getSum(tmp - 1));
        return tmp;
    }
};

2.3.2 方法二:

思路:构造一个n*n+1的数组,求数组大小后在右移1个单位,相当于公式 n ∗ ( n + 1 ) / 2 n*(n+1)/2 n(n+1)/2

class Solution {
public:
    int getSum(int n) {
        char a[n][n+1];//注意数据类型char才能符合条件
        return sizeof(a)>>1;
    }
};

2.4 在O(1)时间删除链表结点

给定单向链表的一个节点指针,定义一个函数在O(1)时间删除该结点。

假设链表一定存在,并且该节点一定不是尾节点。

数据范围
链表长度 [1,500]

样例
输入:链表 1->4->6->8
删掉节点:第2个节点即6(头节点为第0个节点)

输出:新链表 1->4->8

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val = node->next->val;
        node->next = node->next->next;
        //*(node) = *(node->next);
    }
};

2.5 合并两个排序的链表

输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。

数据范围
链表长度 [0,500]。

样例
输入:1->3->5 , 2->4->5

输出:1->2->3->4->5->5

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* merge(ListNode* l1, ListNode* l2) {
        auto dummy = new ListNode(-1), tail = dummy;
        while(l1 && l2)
        {
            if(l1->val < l2->val) 
            {
                tail->next = l1;
                l1 = l1->next;
            }
            else 
            {
                tail->next = l2;
                l2= l2->next;
            }
            tail = tail->next;
        }
        if(l1) tail->next = l1;
        if(l2) tail->next = l2;
        return dummy->next;
    }
};

2.6 左旋转字符串

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。

请定义一个函数实现字符串左旋转操作的功能。

比如输入字符串"abcdefg"和数字 2
,该函数将返回左旋转 2
位得到的结果"cdefgab"。

注意:

数据保证 n
小于等于输入字符串的长度。
数据范围
输入字符串长度 [0,1000]

样例
输入:“abcdefg” , n=2

输出:“cdefgab”

class Solution {
public:
    string leftRotateString(string str, int n) {
        return str.substr(n) + str.substr(0,n);
    }
};

2.7 把字符串转换成整数

请你写一个函数 StrToInt,实现把字符串转换成整数这个功能。

当然,不能使用 atoi 或者其他类似的库函数。

数据范围
输入字符串长度 [0,20]。

样例
输入:“123”

输出:123
注意:

你的函数应满足下列条件:

1.忽略所有行首空格,找到第一个非空格字符,可以是 ‘+/−’ 表示是正数或者负数,紧随其后找到最长的一串连续数字,将其解析成一个整数;
2.整数后可能有任意非数字字符,请将其忽略;如果整数长度为 0,则返回 0;
3.如果整数大于 I N T M A X ( 2 31 − 1 ) INT_MAX(2^{31}−1) INTMAX(2311),请返回 INT_MAX;如果整数小于INT_MIN(−231
) ,请返回 INT_MIN;

class Solution {
public:
    int strToInt(string str) {
        string tmp = "";
        int len = str.length();
        
        //清洗数据空格
        for(int i = 0; i < len; i ++)
        {
            if(char(str[i]) == ' ') tmp = str.substr(i + 1, len - 1);
        }
        if(tmp == "") tmp = str;
        
        //清洗数据正负号
        int tmp_fuhao = 1;
        if(char(tmp[0]) == '+')
        {
            tmp = tmp.substr(1, tmp.length() - 1);
        }
        
        if(char(tmp[0]) == '-') 
        {
            tmp = tmp.substr(1, tmp.length() - 1);
            tmp_fuhao = -1;
        }
        
        //清洗数据尾数
        for(int i = 0; i < tmp.length(); i ++)
        {
        
            if(char(tmp[i]) < '0' || char(tmp[i]) > '9')
            {
                
                tmp = tmp.substr(0, i);
                break;
            }
           
        }
        
        //字符串变整数
        long long res = 0;
        len = tmp.length();
      
        for(int i = 0; i < len; i ++)
        {
            if(tmp[i] == '+' || tmp[i] == '-') continue;
            res = res * 10 + char(tmp[i]) - '0';
            if(res > INT_MAX) break;
        }
        
        if(tmp_fuhao == -1) res = res * -1;
        if(res > INT_MAX) return INT_MAX;
        if(res < INT_MIN) return INT_MIN;
        
        return res;
    }
};

改进点:
1.string的长度str.size()
2.string的切片是字符

2.8 反转链表

定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。

思考题:

请同时实现迭代版本和递归版本。
数据范围
链表长度 [0,30]

样例
输入:1->2->3->4->5->NULL

输出:5->4->3->2->1->NULL

方法一:迭代版

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        while(!head || !head->next) return head;
        
        auto p = head;
        auto q = head->next;
        
        while(q)
        {
            auto o = q->next;
            q->next = p;
            p = q;
            q = o;
        }
        
        head->next = NULL;
        return p;
        
    }
};

方法二:递归方法

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head || !head->next) return head;
        auto tail = reverseList(head->next);
        head->next->next = head;//难点
        head->next = NULL;
        return tail;
        
    }
};

2.9 两个链表的第一个公共结点

输入两个链表,找出它们的第一个公共结点。

当不存在公共节点时,返回空节点。

数据范围
链表长度 [1,2000]

保证两个链表不完全相同,即两链表的头结点不相同。

样例
给出两个链表如下所示:
A: a1 → a2

c1 → c2 → c3

B: b1 → b2 → b3

输出第一个公共节点c1

思路:
在这里插入图片描述
两个指针同时遍历不重复的链条部分,走过的长度是相同的。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *findFirstCommonNode(ListNode *headA, ListNode *headB) {
        auto p = headA, q = headB;
        while(p != q)
        {
            if(p) p = p->next;
            else p = headB;
            if(q) q = q->next;
            else q = headA;
        }
        return p;
    }
};

2.10 删除链表中重复的节点

在一个排序的链表中,存在重复的节点,请删除该链表中重复的节点,重复的节点不保留。

数据范围
链表中节点 val 值取值范围 [0,100]

链表长度 [0,100]

样例1
输入:1->2->3->3->4->4->5

输出:1->2->5
样例2
输入:1->1->1->2->3

输出:2->3

思路:
有可能把头节点删除的题目,需要设置一个虚拟头节点
把相同节点值的看成一段段,p是上一段保留的最后一个节点
q目标是成为下一段的第一个节点,程序运行过程中不一定是

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplication(ListNode* head) {
        //建立虚拟头节点
        auto dummy = new ListNode(-1);
        dummy->next = head;
        auto p = dummy;
        
        while(p->next)
        {
            auto q = p->next;
            //q的更新办法
            //q下一个节点不为空并且q的值等于q下一个节点的值,说明发现有重复的
            while(q->next && q->next->val == q->val) q = q->next;
            
            //p的更新办法
            //如果发现p的下个节点就是q,位置不变,说明没有重复的;否则说明存在重复的
            if(p->next == q) p = q;
            else p->next = q->next;
        }
        return dummy->next;
        
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/918036.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

错误代码0xc0000225要怎么解决?一招教你快速搞定

在运行 Windows 10 操作系统时&#xff0c;您可能会遇到一个错误代码为 0xc0000225 的问题&#xff0c;导致无法正常启动系统。这个错误通常与系统引导文件或硬盘驱动器有关。在本文中&#xff0c;我们将详细介绍多种解决方法来解决 0xc0000225 错误&#xff0c;以帮助您重新恢…

如何选择图像标注工具?

图像标注属于数据标注的一种类型。也许数据标注是人工智能领域不为人知的工作&#xff0c;但也是取得人工智能项目的成功不可或缺的一个环节。数据标注平凡而不平庸&#xff0c;标注的数据质量将直接影响模型的质量。选择恰当高效的标注工具也决定着数据的产出质量。 图像标注作…

AI 绘画Stable Diffusion 研究(十四)SD 图生图+剪映制作人物说话视频

大家好&#xff0c;我是风雨无阻。 前一篇&#xff0c;我们详细介绍了使用 SadTlaker制作数字人视频案例&#xff0c;感兴趣的朋友请前往查看:AI 绘画Stable Diffusion 研究&#xff08;十三&#xff09;SD数字人制作工具SadTlaker使用教程。 对于没有安装 SadTlaker 插件的朋友…

AST+chatGPT降维系列|某cookie反爬之acw_sc__v2分析

关注它&#xff0c;不迷路。 本文章中所有内容仅供学习交流&#xff0c;不可用于任何商业用途和非法用途&#xff0c;否则后果自负&#xff0c;如有侵权&#xff0c;请联系作者立即删除&#xff01; 1. 目标网站 aHR0cHM6Ly93d3cuY2R0LWVjLmNvbS9ob21lL21vcmUtenlnZy5od…

【升职加薪秘籍】我在服务监控方面的实践(8)-elasticsearch 性能监控与分析手段

大家好&#xff0c;我是蓝胖子&#xff0c;之前讲了mysql&#xff0c;redis中间件的监控&#xff0c;今天我们再来看看另一个基础组件elasticsearch&#xff0c;如何对它进行监控&#xff0c;当你思考如何对一个组件进行监控时&#xff0c;四大黄金指标会告诉你答案&#xff0c…

【使用mysql:5.6和 owncloud 镜像,构建一个个人网盘。 安装搭建私有仓库 Harbor】

1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 [rootnode1 ~]# docker pull mysql:5.6 [rootnode1 ~]# docker pull owncloud [rootnode1 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.6 dd3b2a5d…

TypeScript——类型系统与类型推导

前言 TypeScript 是由 Microsoft 开发的一种开放源代码语言。 它是 JavaScript 的一个超集&#xff0c;这意味着你可以在 TypeScript 中使用 JS 已存在的所有语法&#xff0c;并且所有 JavaScript 脚本都可以当作 TypeScript 脚本&#xff0c;此外它还增加了一些自己的语法。T…

如何为短信营销制定最佳策略

营销是一个永无止境的过程&#xff0c;不断寻找新的和创新的方式来吸引更多客户或与他们沟通。短信于1992年首次发出&#xff0c;现在已经31岁了。这可能看起来有点老派&#xff0c;但你会惊讶于这项技术是如何卷土重来的&#xff0c;特别是对于小企业。打开率为98%&#xff0c…

STM32输出3对PWM互补信号做电机控制-C代码

1、使用芯片STM32F103VC 2、打开MXCube新建工程 3、配置下载模式为SW&#xff0c;外部晶振8M&#xff0c;主频72M 4、配置高级定时器1&#xff0c;使用内部晶振&#xff0c;开启互补PWM输出模式 5、配置载波频率10k&#xff0c;即周期为10us &#xff08;定时周期 (Prescal…

c语言实现栈

文章目录 前言一、栈的特征二、栈的实现1、栈的设计2、栈的初始化和销毁3、元素的入栈和出栈4、返回栈顶元素 三、栈的应用 前言 在学习完链表之后&#xff0c;接下来就要了解另外的两个常用的线性数据结构&#xff0c;栈和队列。 一、栈的特征 栈&#xff1a;一种特殊的线性…

斩获多家名校邀请函|检验医师终赴多伦多大学访学深造

M医生学术背景不错&#xff0c;具备较扎实的基础医学理论及较熟练的实验技能&#xff0c;也有一定的英语能力&#xff0c;但因本身不够自信&#xff0c;担心申请不到名校通不过CSC审批。我们先后为其获得新加坡科技研究局&#xff08;A*Star&#xff09;、加拿大麦吉尔大学、多…

为什么企业需要IT服务管理?

什么是IT服务管理? 将IT服务管理功能扩展到技术服务之外&#xff0c;解决以业务为中心通过单一平台&#xff0c;门户和服务目录管理服务供需&#xff0c;通过PaaS/低代码开发工具加速创新和工作流自动化。 为什么企业需要IT服务管理&#xff1f; 为了更好管理公司内不同业务&a…

功能强大、超低功耗的STM32WL55JCI7、STM32WL55CCU7、STM32WL55CCU6 32位无线远距离MCU

STM32WL55xx 32位无线远距离MCU嵌入了功能强大、超低功耗、符合LPWAN标准的无线电解决方案&#xff0c;可提供LoRa、(G)FSK、(G)MSK和BPSK等各种调制。STM32WL55xx无线MCU的功耗超低&#xff0c;基于高性能Arm Cortex-M4 32位RISC内核&#xff08;工作频率高达48MHz&#xff09…

优化ADC 采样计算的简单思路

想法是尽量简化ADC 采样值换算到真实电压的过程&#xff0c;最好是不涉及浮点运算&#xff0c;整数乘除法成本比较低。 原理 对于使用了分压电阻采样输入电压的情形&#xff0c;电路大概是这样&#xff1a; 分压比例为&#xff1a; K R 1 R 2 R 1 (1) K \frac{R1 R2}{R1}…

java 实现N次多项式回归

使用的类库 org.apache.commons.math3 maven <dependency><groupId>org.apache.commons</groupId><artifactId>commons-math3</artifactId><version>3.6.1</version> </dependency> 推荐工具 如果只是做学术研究用&…

摩托车外廓尺寸检测软件

本系统为摩托车外廓尺寸检测软件&#xff0c;该系统共涉及两种测量方法&#xff1a;自动测量和手动测量&#xff0c;旨在测量出每一台摩托车的外廓尺寸&#xff0c;包括但不限于摩托车的车长、车宽、车高、轮距、前悬、后悬、前伸距等需要测量的参数&#xff0c;可通过运行软件…

ATFX汇市:美元指数强势状态延续,市价逼近104关口

环球汇市行情摘要—— 昨日&#xff0c;美元指数上涨0.27%&#xff0c;收盘在103.61点&#xff0c; 欧元贬值0.48%&#xff0c;收盘价1.0846点&#xff1b; 日元贬值0.24%&#xff0c;收盘价145.87点&#xff1b; 英镑贬值0.19%&#xff0c;收盘价1.2733点&#xff1b; 瑞…

Vulnhub: bassamCTF: 1靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.210 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.210 修改hosts文件 爆破出子域名welcome wfuzz -H HOST: FUZZ.bassam.ctf -u http://192.168.111.210 -w /usr/share/wor…

GB28181视频监控国标平台EasyGBS角色绑定设备通道的功能优化

GB28181视频监控国标平台EasyGBS是基于国标GB28181协议、支持多路设备同时接入的视频监控/视频云服务平台&#xff0c;支持对多平台、多终端分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。国标GB28181平台EasyGBS可提供视频直播监控、云端录像、云存储、检索回放、智能告警…

电子器件系列47:稳压二极管

C80857_稳压二极管_BZX84C15LT1G_规格书_ONSEMI(安森美)稳压二极管规格书 232-稳压二极管的串联使用&#xff0c;和普通二极管串联也能灵活稳压_哔哩哔哩_bilibili 基本释义    稳压二极管&#xff0c;英文名称Zener diode&#xff0c;又叫齐纳二极管。    利用pn结反向击穿…