力扣 重排链表-143

重排链表-143

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode* head) {
        //利用快慢指针找到链表的中点
        //慢指针走一步,快指针走两步,快指针走到头循环结束后,慢指针的位置就是链表的中点
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
        }
        //反转链表
        ListNode* cur = NULL;
        ListNode* pre = slow->next;
        slow->next = NULL;//反转链表之前要切断前半部分
        while (pre != NULL){
            ListNode* t = pre->next;
            pre->next = cur;
            cur = pre;
            pre = t;
        }
        //合并链表,将后半部分反转之后的链表中的每个节点插入到前半部分链表每个节点的中间位置
        ListNode* h = head;
        ListNode* c = cur;
        while (c != NULL) 
        {
            /*将前半链表和后半部分链表的当前节点的下一个节点保存下来,
            以便后续的连接操作,因为后面会改变指向,会找不到下一个节点
            */
            ListNode* temph = h->next;
            ListNode* tempc = c->next;
            /*
            将前半部分链表的h节点的下一个节点指向c,将后半部分链表的c节点的下一个节点指向temph,
            就是前半部分链表的h节点的下一个节点(没指向c节点之前的下一个节点)
            */
            h->next = c;
            c -> next = temph;
            /*
            改变指向过后,更新h和c为原来节点(前半部分链表和后半部分链表都没改变指向之前)的下一个节点
            */
            h = temph;
            c = tempc;
            //继续进行循环拼接,直到c为NULL结束循环,则拼接完成
        }   
    }
};

每日问题

什么是多态性?C++中如何实现多态?多态性的好处是什么?

什么是多态性?

多态性(Polymorphism) 是面向对象编程中的一个重要概念,指的是同一个操作或方法可以作用于不同类型的对象,并表现出不同的行为。它使得一个接口可以根据对象的实际类型进行不同的操作。

多态的两种类型:
1.编译时多态(静态多态,早绑定):

在编译时决定调用哪个函数。

主要通过函数重载(Function Overloading)和运算符重载(Operator Overloading)实现。

2.运行时多态(动态多态,晚绑定):

在运行时根据对象的实际类型来决定调用哪个函数。

主要通过虚函数(Virtual Functions)和继承关系来实现。

C++中如何实现多态?

1. 编译时多态(静态多态)

函数重载(Function Overloading):允许多个同名函数根据参数个数或类型不同而有不同的实现。

cpp 复制代码
#include <iostream>
using namespace std;

class Printer {
public:
    void print(int i) {
        cout << "Printing int: " << i << endl;
    }

    void print(double d) {
        cout << "Printing double: " << d << endl;
    }
};

int main() {
    Printer p;
    p.print(10);    // 调用 print(int)
    p.print(3.14);  // 调用 print(double)
    return 0;
}

运算符重载(Operator Overloading):允许自定义运算符的行为。

cpp 复制代码
#include <iostream>
using namespace std;

class Complex {
public:
    int real, imag;
    Complex(int r, int i) : real(r), imag(i) {}

    // 重载加法运算符
    Complex operator + (const Complex &other) {
        return Complex(real + other.real, imag + other.imag);
    }

    void display() {
        cout << real << " + " << imag << "i" << endl;
    }
};

int main() {
    Complex c1(2, 3), c2(4, 5);
    Complex c3 = c1 + c2;  // 调用重载的 + 运算符
    c3.display();           // 输出: 6 + 8i
    return 0;
}
2. 运行时多态(动态多态)

虚函数(Virtual Function) 和 继承: C++ 的多态性主要通过基类指针或引用指向派生类对象并通过 虚函数 实现。虚函数允许子类重写父类的函数,并在运行时根据对象的实际类型调用相应的函数。

cpp 复制代码
#include <iostream>
using namespace std;

// 基类
class Animal {
public:
    virtual void sound() {  // 虚函数
        cout << "Animal makes a sound" << endl;
    }
};

// 派生类
class Dog : public Animal {
public:
    void sound() override {  // 重写虚函数
        cout << "Dog barks" << endl;
    }
};

class Cat : public Animal {
public:
    void sound() override {  // 重写虚函数
        cout << "Cat meows" << endl;
    }
};

int main() {
    Animal* animal1 = new Dog();  // 基类指针指向派生类对象
    Animal* animal2 = new Cat();  // 基类指针指向另一个派生类对象
    
    animal1->sound();  // 调用 Dog 类的 sound() 函数
    animal2->sound();  // 调用 Cat 类的 sound() 函数

    delete animal1;
    delete animal2;
    return 0;
}

输出:

cpp 复制代码
Dog barks
Cat meows

在上面的例子中:

sound() 是一个虚函数。

通过基类 Animal 的指针 animal1 和 animal2 来调用派生类 Dog 和 Cat 中的 sound() 方法。

由于 sound() 是虚函数,程序会在运行时动态绑定正确的函数调用(即调用 Dog 或 Cat 类中的重写版本),而不是基类的 sound()。

如何实现运行时多态:

1.虚函数:

在基类中声明函数为 virtual,表示该函数希望被子类重写。

2.重写:

子类通过 override 关键字或仅通过函数签名重写父类的虚函数。

3.多态:

使用基类指针或引用调用虚函数,实际调用的是派生类中的实现。

多态性的好处:

1.代码的扩展性:

多态使得程序在增加新功能时不需要修改现有代码。你可以新增子类,而不需要修改调用基类的代码。

2.提高代码的灵活性和可维护性:

通过多态,程序可以更加灵活地根据对象的实际类型执行不同的操作,减少了条件语句或类型检查。

3.实现接口和抽象:

多态允许定义统一的接口或抽象类,而具体的行为则由不同的子类实现。这可以使得代码在使用时更加一致且易于理解。

4.降低耦合度:

多态性使得不同模块之间的耦合度降低,因为你可以通过基类接口与派生类进行交互,而不需要关心派生类的具体实现。

多态性的注意事项:

1.虚函数的使用:

在基类中定义的虚函数通常需要在派生类中被重写,否则可能会调用基类的实现,导致不符合预期的行为。

2.析构函数:

如果类有虚函数,通常也需要将析构函数定义为虚函数,以确保在删除通过基类指针指向派生类对象时能够正确调用派生类的析构函数,从而避免资源泄漏。

3.性能开销:

使用虚函数可能带来一些性能开销,因为每次调用虚函数时都需要通过虚表(VTable)进行动态查找。

总结:

1.多态性 是面向对象编程的重要特性,允许通过统一的接口操作不同类型的对象,且表现出不同的行为。

2.在 C++ 中,编译时多态通过函数重载和运算符重载实现,运行时多态通过虚函数和继承实现。

3.多态性增强了代码的灵活性、扩展性、可维护性,减少了耦合度。

相关推荐
大熊猫侯佩26 分钟前
Swift 数学计算:用 Accelerate 框架让性能“加速吃鸡”
算法·swift
杰克尼1 小时前
2. 两数相加
算法
无聊的小坏坏1 小时前
单调栈通关指南:从力扣 84 到力扣 42
c++·算法·leetcode
_Coin_-1 小时前
算法训练营DAY29 第八章 贪心算法 part02
算法·贪心算法
阿维同学1 小时前
自动驾驶关键算法深度研究
人工智能·算法·自动驾驶
今天背单词了吗9802 小时前
算法学习笔记:11.冒泡排序——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·学习·算法·排序算法·冒泡排序
倔强的小石头_5 小时前
【C语言指南】函数指针深度解析
java·c语言·算法
Yasin Chen5 小时前
C# Dictionary源码分析
算法·unity·哈希算法
_Coin_-6 小时前
算法训练营DAY27 第八章 贪心算法 part01
算法·贪心算法
许小燚10 小时前
线性表——双向链表
数据结构·链表