数据结构——链表——模板类实现双向链表——先完成再完美——持续更

链表:概念,实现,《数据结构》这里实现是基于模板的

C++语言基础,指针,引用。模板。《C++Primer》有些进阶用法放在语言学习的目录

LeetCode应用,会更新在LeetCode150,目前这个系列先暂停,数据结构更新一期,再更对应的题目解题。

新手村入门,可以根据下面实现的过程中,忘记的知识点,再回头看。

新手村入门

链表概念

列表:逻辑上有序,物理上无序(动态存储策略)【与向量一样,列表也是由具有线性逻辑次序的一组元素的集合。链表结构一般化推广】

好处:降低动态操作成本(插入,删除)O(1)

劣势:静态操作(查找,需要扫描一遍列表元素)O(n)

 L = \left \{ a_{0}, a_{1},..., a_{n-1} \right \}

元素称为节点;

模板函数的创建与模板类的创建

C++中的模板是一种允许我们为类或者函数定义一种通用模式的机制,这种通用模式可以用于创建多种数据类型的类或函数实例,而无需为每个类型都编写单独的代码。模板有两种主要类型:函数模板和类模板。

函数模板入门

函数模板允许我们定义一个通用的函数,该函数可以接受多种数据类型的参数。模板参数列表在函数定义之前用尖括号<>括起来,并紧跟在template关键字之后。

下面是一个简单的函数模板示例,它用于交换两个值的位置:

template <typename T> // 模板参数列表,typename T 是一个类型模板参数  
void swap(T& a, T& b) {  
    T temp = a;  
    a = b;  
    b = temp;  
}

在这个例子中,T是一个类型模板参数,它在编译时会被实际类型(如intdoublestd::string等)替换。

类模板

类模板允许我们定义一个通用的类,该类可以用于多种数据类型。与函数模板类似,类模板的模板参数列表也位于类声明之前,并紧跟在template关键字之后。

下面是一个简单的类模板示例,它用于创建一个动态数组:

template <typename T> // 模板参数列表  
class Array {  
private:  
    T* data;  
    size_t size;  
  
public:  
    Array(size_t s) : size(s), data(new T[s]) {}  
    ~Array() { delete[] data; }  
  
    T& operator[](size_t index) {  
        return data[index];  
    }  
  
    // 其他成员函数...  
};

在这个例子中,T是一个类型模板参数,它决定了数组data中元素的类型。

模板参数列表

模板参数列表可以包含多个类型模板参数,也可以包含非类型模板参数(如整数常量或指针)。类型模板参数用typenameclass关键字声明(两者在模板参数声明中是等价的),而非类型模板参数可以是整数、指针或其他非类型值。

下面是一个包含多个类型模板参数的类模板示例:

template <typename Key, typename Value> // 包含两个类型模板参数  
class Map {  
    // ... 类的实现,可能包含以Key和Value为类型的成员 ...  
};

下面是一个包含非类型模板参数的函数模板示例:

template <typename T, size_t N> // 包含一个类型模板参数和一个非类型模板参数  
void printArray(const T (&array)[N]) {  
    for (size_t i = 0; i < N; ++i) {  
        std::cout << array[i] << ' ';  
    }  
    std::cout << std::endl;  
}

在这个例子中,T是一个类型模板参数,而N是一个非类型模板参数(一个size_t类型的常量)。

OOP封装

在面向对象编程(OOP)中,封装(Encapsulation)是一个核心概念,它指的是将对象的属性和方法(或称为成员变量和成员函数)隐藏在对象内部,只通过公共接口(通常是公有方法)与外部世界进行交互。封装有助于隐藏对象的内部细节,防止外部代码直接访问或修改对象的内部状态,从而确保对象的完整性和安全性。

未封装处理通常指的是在编程中没有使用封装的概念,对象的属性和方法都是公开的,可以直接被外部代码访问和修改。这种编程方式可能会导致代码的可读性、可维护性和安全性降低。

下面是一个简单的例子来说明封装处理和未封装处理的区别:

未封装处理(不推荐)
class Person {  
public:  
    int age; // 年龄是公开的  
  
    // 没有提供任何方法来修改年龄  
};  
  
int main() {  
    Person p;  
    p.age = -5; // 外部代码可以直接修改年龄,甚至设置为一个不合理的值  
    return 0;  
}

在这个例子中,Person 类的 age 属性是公开的,任何外部代码都可以直接访问和修改它。这可能导致问题,因为年龄不应该是一个负数。

封装处理(推荐)
class Person {  
private: // 使用私有访问修饰符来隐藏属性  
    int age;  
  
public:  
    // 提供公有方法来设置年龄  
    void setAge(int newAge) {  
        if (newAge >= 0) { // 添加一个检查来确保年龄是非负的  
            age = newAge;  
        } else {  
            std::cerr << "Age cannot be negative!" << std::endl;  
        }  
    }  
  
    // 提供公有方法来获取年龄  
    int getAge() const {  
        return age;  
    }  
};  
  
int main() {  
    Person p;  
    p.setAge(-5); // 尝试设置一个不合理的年龄  
    // 输出:Age cannot be negative!  
    // 由于设置了检查,年龄没有被修改为-5  
    std::cout << "Person's age: " << p.getAge() << std::endl; // 输出:Person's age: 0(或之前的值,如果之前有设置过)  
    return 0;  
}

在这个封装处理的例子中,Person 类的 age 属性是私有的,外部代码不能直接访问或修改它。相反,我们提供了两个公有方法 setAgegetAge 来分别设置和获取年龄。在 setAge 方法中,我们添加了一个检查来确保年龄是非负的。这样,即使外部代码尝试设置一个不合理的年龄,它也会被拒绝,从而确保了对象的完整性和安全性。

函数模板进阶用法和注意(另一篇总结中)

指针和引用的区别 (另一篇总结中)

《数据结构(C++语言版)》不懂的专业术语

秩,线性代数的一个概念,极大线性无关。。。还在上大学的别学我,我的线代还给老师了。

专业解释,百度或者书本,在下面的链表中,简单理解为表示一个位置,像数组下标,秩相同(下标相同)。

ADT 抽象数据类型,一般指数据的某种抽象和操作

API 应用程序结构,软件之间的交互

我们下面的目标是,根据书中提供的 ADT,代码模板,写出一个可以运行的模板链表类,Let's Go!

链表之旅

第一个任务,列表节点 

注意:默认链表中每个节点都有数据,并且未对数据进行封装处理。

第二个任务,列表的实现

面向对象程序设计课程作业 1. 请创建一个数据类型为T的链表类模板List,实现以下成员函数: 1) 默认构造函数List(),将该链表初始化为一个空链表(10分) 2) 拷贝构造函数List(const List& list),根据一个给定的链表构造当前链表(10分) 3) 析构函数~List(),释放链表中的所有节点(10分) 4) Push_back(T e)函数,往链表最末尾插入一个元素为e的节点(10分) 5) operator<<()友元函数,将链表的所有元素按顺序输出(10分) 6) operator=()函数,实现两个链表的赋值操作(10分) 7) operator+()函数,实现两个链表的连接,A=B+C(10分) 2. 请编写main函数,测试该类模板的正确性: 1) 用List模板定义一个List类型的模板类对象int_listB,从键盘读入m个整数,调用Push_back函数将这m个整数依次插入到该链表中;(4分) 2) 用List模板定义一个List类型的模板类对象int_listC,从键盘读入n个整数,调用Push_back函数将这n个整数依次插入到该链表中;(4分) 3) 用List模板定义一个List类型的模板类对象int_listA,调用List的成员函数实现A = B + C;(4分) 4) 用cout直接输出int_listA的所有元素(3分) 5) 用List模板定义List类型的模板类对象double_listA, double_listB, double_listC,重复上述操作。(15分) 3. 输入输出样例: 1) 输入样例 4 12 23 34 45 3 56 67 78 3 1.2 2.3 3.4 4 4.5 5.6 6.7 7.8 2) 输出样例 12 23 34 45 56 67 78 1.2 2.3 3.4 4.5 5.6 6.7 7.8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值