Skip to content

复合数据类型

约 4756 字大约 16 分钟

C++

2025-03-04

本文作者:程序员飞云

本站地址:https://www.flycode.icu

数组

相同类型的数据存放在里面,内存地址是连续的,占用相同大小的空间

  1. 定义
	// 数组定义
	int a[2] ;

	// 外界设置长度
	const  int n = 3;
	double a2[n];
  1. 初始化
	int a3[4] = { 1,2,3,4 };
	int a4[] = { 1,2,3 };
	int a5[10] = { 1,2,3 };// 其余初始值为0
	//int a6[2] = { 1,2,3 };//错误,个数不对
	//int a6[4] = a3; // 错误不能使用一个数组给另一个数组赋值

如果没有进行初始化,默认的数组值是0xCC

  1. 数组访问

下表默认从0开始到len-1

int a[3] = { 1,2,3 };
cout << "a[0]=" << a[0] << endl;
cout << "a[1]=" << a[1] << endl;
cout << "a[2]=" << a[2] << endl;
  1. 计算数组长度

这里面没有设置对应的size,所以只能手动计算

int aSize = sizeof(a) / sizeof(a[0]);
  1. 遍历数组
	int aSize = sizeof(a) / sizeof(a[0]);

	// 下标遍历
	for (int i = 0; i < aSize; i++) {
		cout << "a[" << i << "]=" << a[i] << endl;
	}

	// 增强for
	for (int num : a) {
		cout << num << endl;
	}

多维数组

  1. 初始化
	int arr[3][4] = { {1,2,3} ,{4,5,6} };
	int arr2[3][4] = { 1,2,3,4,5,6 }; // 和上面的一样
	int arr3[][4] = { 1,2,3,4,5,6 };  // 第一个可以省略
  1. 访问元素
cout << arr[1][2] << endl;
  1. 计算行,列长度
	int rowSize = sizeof(arr) / sizeof(arr[0]);
	int colSize = sizeof(arr[0]) / sizeof(arr[0][0]);
	cout << "行个数" << colSize<<endl;
	cout << "列个数" << rowSize << endl;
  1. 遍历

下标遍历

for (int i = 0; i < rowSize; i++) {
	for (int j = 0; j < colSize; j++) {
		cout << "arr[" << i << "][" << j << "]=" << arr[i][j] << endl;
	}
}

增强for遍历

	for (auto& row : arr) {
		for (auto num : row) {
			cout << num << endl;
		}
	}

&引用

auto:由编辑器自动分析

数组排序

选择排序

选择排序是从当前数组里面选出最小(最大)元素放在初始位置,再从剩余的元素里面取出最小(最大)元素,继续放在已经排序好的元素后面,直到所有的数据都排序完成

int main() {
	// 选择排序
	int arr[7] = { 4,2,5,6,1,3,2 };
	int size = sizeof(arr) / sizeof(arr[0]);

	for (int i = 0; i < size; i++) {
		for (int j = i + 1; j < size; j++) {
			if (arr[j] < arr[i]) {
				int temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
			}
		}
	}


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

冒泡排序

会将最小(最大)的线排列到数组的最后,然后再次判断剩下来的元素,重复相同的操作。

	for (int i = 0; i < size; i++) {
		for (int j = 0; j < size - i - 1; j++) {
			if (arr[j] > arr[j + 1]) {
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}

模板类vector

因为数组使用极为不方便,每次都需要手动计算数组长度,而且必须要指定数组的大小,vector长度不是固定的。

引入vector

#include<vector>
using namespace std;
  1. 默认初始化
vector<int> v1;
  1. 列表初始化
	vector<char> v2 = { 'a','b','c' };
	vector<char> v3 { 'a','b','c' };
  1. 直接初始化
	vector<short> v4(5);// 创建5个元素
	vector<long> v5(5, 100); // 默认值都是100
  1. 访问元素
cout<<v2[2]<<endl;
  1. 修改元素
	v2[2] = 'x';
	cout << v2[2] << endl;
  1. 遍历元素
for (int i = 0; i < v2.size(); i++)
{
	cout<<"v2["<<i<<"]=" << v2[i] << endl;
}

for (char ch : v2) {
	cout <<  ch<< endl;
}
  1. 添加倒序元素
v2.push_back('r');
  1. 删除倒序元素
v2.pop_back();

vector是数组的上层抽象,长度不固定,运行效率低。

C++11里面还增加了array,数组类似,长度固定,方便。

字符串

string

  1. 引入string
#include<string>;
using namespace std;
  1. 默认初始化
string s1;
  1. 拷贝初始化
string s2 = "Hello world";
  1. 直接初始化
	string s3("hello word");
	string s4(8, 's');// 8个s连接在一起
  1. 访问字符
cout << s4[4] << endl;
  1. 修改字符
s4[5] = 'h';
  1. 遍历字符
	for (int i = 0; i < s4.size(); i++) {
		cout << s4[i]<<"\t" ;
	}
	cout << endl;

	for (char ch : s4) {
		cout << ch << "\t";
	}
	cout << endl;
  1. 大小写转换
for (int i = 0; i < s4.size(); i++) {
	s4[i] = toupper(s4[i]);
}
  1. 字符串拼接
	string s5 = "hello";
	string s6 = "world";
	string s7 = s5 + s6;
	cout << s7 << endl;
	string s8 = s5 + "," + s6;
	cout << s8 << endl;

	//string s9 = "hello" + "world";错误
  1. 字符串比较
	s5 = "hello";
	s6 = "hello world";
	s7 = "hhh";
	cout << (s5 == s6 ? "true" : "false") << endl;
	cout << (s5 < s6 ? "true" : "false") << endl;
	cout << (s5 < s7 ? "true" : "false") << endl;

总结

使用string的时候,如果进行比较,==只会比较当前位数上的字符值的大小。

字符串拼接的时候,不能使用两个纯字符串相加,否则会报错

字符数组

  1. 字符数组初始化
	char str[] = { 'h','e','l','l','o' };
  1. 字符数组转换为字符串初始化
	char str2[] = { 'h','e','l','l','o','\0' };
  1. 计算长度
char str3[] = "hello"; // size=6,后面还有一个\0
cout << sizeof(str3) << endl;

一般不推荐使用这个,因为如果是字符串的话,直接使用string就可以,但是string底层是char数组,所以这个还是有必要学习一下的。

读取输入字符串

  1. 简单读取多个字符串
string str1, str2;
cin >> str1 >> str2;
cout << str1 << str2 << endl;
  1. getline读取多个单词
	string str3;
	getline(cin,str3);
	cout << str3 << endl;
  1. cin.get()读取单个单词
char ch;
ch = cin.get();
cout << "ch=" << ch << endl;
char str4[20];
cin.get(str4, 20);

读写文件

ifstream

ofstream

  1. 引入头文件
#include<fstream>
  1. 读取文件
ifstream input("vector.cpp");
  1. 逐词读取
	string word;
	while (input >> word) {
		cout << word << endl;
	}
image-20240213160244505
image-20240213160244505
  1. 逐行读取
	string line;
	while (getline(input, line)) {
		cout << line << endl;
	}
image-20240213160322612
image-20240213160322612
  1. 逐个字符读取
	char ch;
	while (input.get(ch)) {
		cout << ch << endl;
	}
image-20240213160726449
image-20240213160726449
  1. 写入文件

没有指定路径,写入到当前项目里面,需要在资源管理器里面

ofstream output("output.txt");
char ch;
while (input.get(ch)) {
	output << ch << endl;
}

完整代码

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

int main() {
	ifstream input("vector.cpp");
	
	// 逐词读取
	//string word;
	//while (input >> word) {
	//	cout << word << endl;
	//}

	//// 逐行读取
	//string line;
	//while (getline(input, line)) {
	//	cout << line << endl;
	//}

	//// 逐字符读取
	//char ch;
	//while (input.get(ch)) {
	//	cout << ch << endl;
	//}
    
    ofstream output("output.txt");
	char ch;
	while (input.get(ch)) {
		output << ch << endl;
	}

}

结构体

有点类似Java里面的类

1. struct定义

struct student
{
	string name;
	int age;
	double score;
};

2. 创建对象和初始化对象

可以在创建struct时候创建

struct Student
{
	string name;
	int age;
	double score;
}stu2, stu3{"test",22,88};

也可以在方法里面创建

Student student = { "hello",20,100 };
Student stu1{ "hello",20,100 };
// 拷贝复制
Student student4 = student;

3. 访问对象数据

cout << "姓名:" << student.name << "\t年龄:" << student.age << "\t分数:" << student.score << endl;

也可以定义函数直接调用就可以

void printInfo(Student student) {
	cout << "姓名:" << student.name << "\t年龄:" << student.age << "\t分数:" << student.score << endl;
}

4. 赋值

stu2.name = "ww";
stu2.age = 22;
stu2.score= 100;

5.结构体数组

	Student stu[] = { {"张三",12,88},{"里斯",44,34} };
	for (Student stu5 : stu) {
		printInfo(stu5);
	}
#include<iostream>
using namespace std;

struct Student
{
	string name;
	int age;
	double score;
}stu2, stu3{ "wz",21,60.0 };

void printInfo(Student student) {
	cout << "姓名:" << student.name << "\t年龄:" << student.age << "\t分数:" << student.score << endl;
}


int main9() {
	// 创建数据对象初始化
	Student student = { "hello",20,100.0 };
	Student stu1{ "hello",20,100.0 };
	// 拷贝复制
	Student student4 = student;


	// 访问数据
	//cout << "姓名:" << student.name << "\t年龄:" << student.age << "\t分数:" << student.score << endl;
	printInfo(student);

	// 赋值
	stu2.name = "ww";
	stu2.age = 22;
	stu2.score= 100;
	printInfo(stu2);


	// 结构体数组
	Student stu[] = { {"张三",12,88},{"里斯",44,34} };
	for (Student stu5 : stu) {
		printInfo(stu5);
	}

	return 0;

}

枚举类型

enum week {
	Mon,Tue,Wed,Thu,Fri,Sat,Sun
};
#include<iostream>
using namespace std;

enum week {
	Mon,Tue,Wed,Thu=10,Fri,Sat,Sun
};

int main() {
	
	week w1 = Mon;
	
	// 强制转换
	week w3 = week(3);
	// 获取的是对应的下标 0
	cout << w1 << endl;
	// 值为3
	cout << w3 << endl;

	week w4 = Thu;
	// 值为10,后续的下标都是从10开始
	cout << w4 << endl;

	week w5 = week(100);
	cout << w5 << endl;
}

指针

指针的用法

可以通过指针访问指向那个数据对象,间接访问对象

	int* p1;
	long* p2;
	long long* p3;

64位默认的字节长度是8

内存具体存放方式

image-20240213165332294
image-20240213165332294
#include<iostream>
using namespace std;

int main() {
	int* p1;
	long* p2;
	long long* p3;

	cout << "p1的内存长度为" << sizeof(p1) << endl;
	cout << "p2的内存长度为" << sizeof(p2) << endl;

	int a = 10;
	int b = 20;
	long c = 35;

	// a的地址拿出来给p1
	p1 = &a;
	p2 = &c;

	cout << "a的地址是" << &a << endl;
	cout << "b的地址是" << &b << endl;
	cout << "c的地址是" << &c << endl;

	cout << "p1=" << p1 << endl;
	cout << "p2=" << p2<< endl;
}
image-20240213165823791
image-20240213165823791

内存调试

image-20240213170540047
image-20240213170540047

解引用操作符*

cout << "p1的值为" << *p1 << endl;
// 修改p1
*p1 = 12;
cout << "p1的值为" << *p1 << endl;
image-20240213170844082
image-20240213170844082

无效指针/野指针

定义一个指针,如果不进行初始化,内容是不确定的,如果此时把这个指针的内容当作一个地址访问,就有可能访问的是一个无效的对象,如果是内存核心区域,修改内容就可能导致系统崩溃。

int* p3;
*p3 = 100;
image-20240213171242566
image-20240213171242566

空指针

我们不想要初始化指针,可以使用如下三种方法

	int* p4 = nullptr;
	p4 = NULL;
	p4 = 0;

void指针

可以存放任意对象的地址

	int i = 10;
	char ch = 'c';
	long s = 100;

	void* vp = &i;
	vp = &ch;
	vp = &s;
	// 不能使用*,无法推测

只能存储对应的地址,和比较,不能用来解引用

二级指针

指针也有自己的内存地址,一个指针指向另一个内存的地址。

	int i = 10;
	int* pi = &i;
	int** ppi= &pi;

	cout << "i="<<i << endl;
	cout << "pi=" << pi << endl;
	cout << "ppi=" << ppi << endl;
	cout << "*pi的值是" << *pi << endl;
	cout << "*ppi的值是" << *ppi << endl;
	cout << "**ppi的值是" << **ppi << endl;
image-20240213173225430
image-20240213173225430

指针和const

  1. 指向常量的指针
	const int c1 = 10, c2 = 56;
	const int* pc = &c1;

	pc = &c2;
	//*pc = 100; 常量不可修改
	pc == &i; // 可以指向变量
  1. 指针常量

不能再次指向其他的变量,但是可以修改变量的值

	// 指针常量,必须是变量
	int* const cp = &i;

也可以结合,变成指向常量的指针常量

const int* const cpp = nullptr;

指针和数组

数组本质上也是一个指针,而数组名就是一个指针

	int arr[] = { 1,2,3,4,5,6 };
	cout << arr << endl;
	cout <<"&arr[0]" << &arr[0] << endl;
	cout << "&arr[0]" << &arr[1] << endl;

	int* arrp = arr;
	cout << "* arrp=" << *arrp << endl;
	*arrp = 100;
	cout << "* arrp=" << *arrp << endl;

数组元素操作

	cout << "arrp=" << arrp << endl;
	cout << "arrp+1=" << arrp + 1 << endl;

	cout << *arrp + 3 << endl;
	cout << *(arr + 3) << endl;

	*(arr + 3) = 122;

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

数组指针和指针数组

// 指针数组
int* pa[5] = {};
// 数组指针
int(*ap)[5] = {};

指针数组:是数组,指向数组的指针,存放元素(长度是5*8)当前数组长度

数组指针:是指针,指针存放地址,(长度是8)

	// 指针数组
	int* pa[5] = {};
	// 数组指针
	int(*ap)[6] = {};

	int arrt[] = { 1,2,3,4,5,6 };

	pa[0] = &i;
	pa[1] = arrt;
	pa[2] = arrt + 2;

	ap = &arrt; // 指向arrt整个数组
	// 指针数组
	int* pa[5] = {};
	// 数组指针
	int(*ap)[6] = {};

	int arrt[] = { 1,2,3,4,5,6 };

	pa[0] = &i;
	pa[1] = arrt;
	pa[2] = arrt + 2;


	ap = &arrt;
	// 得到arr的地址
	cout << "*ap=" << *ap << endl;
	// 获取第一个元素
	cout << "**ap=" << **ap << endl;
	// 获取第二个元素
	cout << "*(*ap+1)=" << *(*ap+1) << endl;

引用

引用的使用

在变量前面添加符号&,表示另一个变量的引用。引用必须被初始化。

引用不会存储对象,而是和初始值绑定在一起,之后无法绑定其他的对象,相当于别名,快捷方式,操作引用就是操作原对象

int main() {

	int a = 10;
	int b = 12;

	int& ref = a;

	cout << "ref=" << ref << endl;

	cout << "a的地址=" << &a << endl;

	cout << "ref的地址=" << &ref << endl;

	ref = b;
	cout << "ref的地址=" << &ref << endl;
    
    
	ref = 15;
	cout << "a=" <<a << endl;
}
image-20240214164253828
image-20240214164253828

引用的引用,也是指向的原来的引用

int & rref = ref

对常量的引用

常量是不可以修改的,所有常量引用也是不可修改的

	const int zero = 0;

	const int& cref = zero;

常量引用初始化要求很低,和变量引用不一样,只要是转换为它指定类型的所有表达式,都可以初始化

	double d = 3.14;
	const int& ref4 = d;

引用和指针

  1. 引用和指针常量

引用类似于指针常量

int main() {
	int a = 10;

	// 指针常量
	int* const p = &a;

	// 引用
	int& ref = a;
	
	cout << "查看值--------------------" << endl;
	cout << "a=" << a << endl;
	cout << "p=" << p << endl;
	cout << "ref=" << ref << endl;

	cout << "修改值------------------" << endl;
	ref = 20;
	cout << "a=" << a << endl;

	*p = 30;
	cout << "a=" << a << endl;

}
image-20240214170451984
image-20240214170451984

但是引用和指针常量还是有区别的

引用没有内存地址,保存另一个对象的内存地址,而指针需要创建内存地址的。

cout << "a地址=" << &a << endl;
cout << "p的值=" << &p << endl;
cout << "p地址=" << &p << endl;
cout << "ref地址=" << &ref<< endl;
image-20240214170810900
image-20240214170810900

绑定指针的引用

	int* ptr = &a;
	int*& pref = ptr;

没有指向引用的指针

案例

1. 翻转数组

将数组里面的元素都翻转

例如{1,2,3,4,5,6,7,8}->

  1. 最简单的方法就是创建一个新的数组,然后逆序填充这个数组
int main() {

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

	// 1. 创建新数组
	int newArr[n];

	for (int i = 0; i < n; i++) {
		newArr[n-1-i] = arr[i];
	}


	int size = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < size; i++) {
		cout << newArr[i] << "\t";
	}

	cout << endl;
	
	return 0;
}
  1. 双指针,定义左右位置,交换左右位置的值,然后左指针往右走,右指针往左走
	int left = 0;
	int right = n - 1;

	while (left < right) {
		int temp = arr[left];
		arr[left] = arr[right];
		arr[right] = temp;
		left++;
		right--;
	}

	int size = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < size; i++) {
		cout << arr[i] << "\t";
	}

	cout << endl;

2. 检验幻方

不同的数字组成方阵,并且每行,每列,每个对角线的和都相等。

image-20240214174009756
image-20240214174009756
#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 rowSize = sizeof(arr) / sizeof(arr[0]);
	int colSize = sizeof(arr[0]) / sizeof(arr[0][0]);
		

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

	bool isValid = true;

	for (int i = 0 ; i < rowSize; i++) {
		int sum = 0;
		// 检验每一行
		for (int j = 0; j < colSize; j++) {
			sum += arr[i][j];
		}

		if (sum != target) {
			isValid = false;
			break;
		}
		else {
			sum = 0;
			continue;
		}

		// 检验每一列
		sum += arr[i][0];
		if (sum != target) {
			isValid = false;
			break;
		}
		else {
			sum = 0;
			continue;
		}


		// 检验对角线
		for (int j = 0; j < colSize; j++) {
			sum += arr[j][j];
			sum += arr[i][i];
		}
		if (sum != target) {
			isValid = false;
			break;
		}
		else {
			sum = 0;
			continue;
		}
	}

	string res = isValid == true ? "符合" : "不符合";

	cout << res << endl;
}

以上代码过于冗余,重复的判断,以及多个for循环,我们可以进行优化

#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 rowSize = sizeof(arr) / sizeof(arr[0]);
	int colSize = sizeof(arr[0]) / sizeof(arr[0][0]);
		

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

	bool isValid = true;
	
    // 对角线的和
	int sumLeft = 0;
	int sumRight = 0;

	for (int i = 0 ; i < rowSize; i++) {
        // 每行每列的和
		int sumRow = 0;
		int sumCol = 0;
	
		// 检验
		for (int j = 0; j < colSize; j++) {
			sumRow += arr[i][j];
			sumCol += arr[j][i];
		}

		if (sumRow != target || sumCol !=target ) {
			isValid = false;
			break;
		}
		
        // 这个必须完成所有的遍历后才能进行判断
		sumLeft += arr[i][i];
		sumRight += arr[i][n - i - 1];
	}

	if (sumLeft != target || sumRight != target) {
		isValid = false;
	}

	string res = isValid == true ? "符合" : "不符合";

	cout << res << endl;
}

3. 大整数相加

两个字符串形式的非负大整数num1和num2,计算和。

我们需要从最后一位进行相加,判断是否有进位,如果有进位就记录下来。

#include<iostream>
#include<string>

using namespace std;

int main() {
    string num1 = "32535943020935527435432875";
    string num2 = "9323298429842985843509";

    string result;

    // 指向个位
    int p1 = num1.size() - 1;
    int p2 = num2.size() - 1;

    // 进位
    int carry = 0;

    // 两数的末尾位数相加,carry还有进位
    while (p1 >= 0 || p2 >= 0 || carry == 1) {
        // 判断遍历是否完成,完成就补0
        int number1 = (p1 >= 0) ? (num1[p1] - '0') : 0;
        int number2 = (p2 >= 0) ? (num2[p2] - '0') : 0;

        int sum = number1 + number2 + carry;
        carry = sum / 10;
        sum = sum % 10;
        result += sum + '0';  // 和个位保存到结果中
        // 指针移动
        p1--;
        p2--;
    }

    // 结果反转
    int left =0;
    int right = result.size()-1;
    while(left<right){
        char ch = result[left];
        result[left] = result[right];
        result[right] = ch;
        left++;
        right--;
    }

    cout << "值为" << result << endl;
    return 0;
}

4. 旋转图像

给定二维数组,将这个二维数组顺时针旋转90°

{

​ {5,1,9,11},

​ {2,4,8,10},

​ {13,3,6,7},

}

转换为

{

​ {15,13,2,5},

​ {14,3,4,1},

​ {12,6,8,9},

}

根据数学方法

我们可以先进行矩阵转置(以对角线为对称轴,两边元素互换),然后再反转每一行里面的数组元素

#include<iostream>
using namespace std;

int main() {
	int n = 4;
	int arr[4][4] = {
		{5,1,9,11},
		{2,4,8,10},
		{13,3,6,7},
		{15,14,12,16}
	};

	int rowSize = sizeof(arr) / sizeof(arr[0]);
	int colSize = sizeof(arr[0]) / sizeof(arr[0][0]);
	int newArr[4][4];

	// 矩阵转置
	for (int i = 0; i < rowSize; 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 < rowSize; i++) {
		for (int j = 0; j < colSize/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;
	}

	return 0;
}

里面有一个关键点是进行转置的时候,我们只需要转换一半,如果全部转置,就右变回了原来的数据

5. 反转链表

力扣题目 反转链表

定义链表,可以在头文件里面定义链表,避免重复创建,list_node.h

#pragma once
struct ListNode
{	
	int value;
	ListNode* next;
};

简单的定义链表和打印链表

#include<iostream>
using namespace std;
#include "list_node.h"

int main() {
	// 定义链表 1->2->3->4->5
	ListNode node5 = { 5,nullptr };
	ListNode node4 = { 4, &node5 };
	ListNode node3 = { 3, &node4 };
	ListNode node2 = { 2, &node3 };
	ListNode node1 = { 1, &node2 };

	// 头节点
	ListNode* head = &node1;

	// 打印
	ListNode* np = head;

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

反转链表

我们可以定义两个指针,pre指向前一个节点,cur指向当前节点,通过操作原链表反转,详情步骤在算法,链表反转专题里面。

#include<iostream>
using namespace std;
#include "list_node.h"

int main() {
	// 定义链表 1->2->3->4->5
	ListNode node5 = { 5,nullptr };
	ListNode node4 = { 4, &node5 };
	ListNode node3 = { 3, &node4 };
	ListNode node2 = { 2, &node3 };
	ListNode node1 = { 1, &node2 };

	// 头节点
	ListNode* head = &node1;

	// 打印
	ListNode* np = head;

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

	// 指向前一个节点
	ListNode* pre = nullptr;
	// 遍历当前节点
	ListNode* cur = head;
	// 反转链表
	while (cur) {
		ListNode* next = (*cur).next;
		(*cur).next = pre;
		// 两个节点移动
		pre = cur;
		cur = next;
	}

	ListNode* newList = pre;
	// 打印
	np = newList;

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

}

里面的(*cur).next都可以转换为cur->next的形式,方便编写

#include<iostream>
using namespace std;

#include "list_node.h"

int main() {
	// 初始化链表 1->2->3->4->5->6
	ListNode node5 = { 5,nullptr };
	ListNode node4 = { 4,&node5 };
	ListNode node3 = { 3,&node4 };
	ListNode node2 = { 2,&node3 };
	ListNode node1 = { 1,&node2 };

	ListNode* head = &node1;

	ListNode* np = head;

	while (np) {
		cout << np->value << "\t";
		np = np->next;
	}
	cout << "NULL" << endl;


	ListNode* pre = nullptr;
	ListNode* cur = head;

	while (cur) {
		ListNode* next = cur->next;
		cur->next = pre;
		pre = cur;
		cur = next;
	}

	ListNode* newList = pre;

	np = newList;

	while (np) {
		cout << np->value << "\t";
		np = np->next;
	}
	cout << "NULL" << endl;
}

贡献者

  • flycodeuflycodeu

公告板

2025-03-04正式迁移知识库到此项目