7-1 单链表基本操作
在 C/C++ 中,.
(点)和 ->
(箭头)运算符用于访问结构体或类的成员,但它们的使用场景不同。
1. .
运算符
.
运算符用于访问结构体或类的成员,通过对象或结构体变量直接访问。
2. ->
运算符
->
运算符用于访问指向结构体或类的指针的成员。它简化了通过指针访问成员的过程。
示例:
struct Point {
int x,y;
};
Point p; // 创建结构体变量 p
p.x = 10; // 使用 . 访问成员 x
p.y = 20; // 使用 . 访问成员 y
cout << "Point: (" << p.x << ", " << p.y << ")" << endl; // 输出: Point: (10, 20)
Point* p1 = (Point*)malloc(sizeof(Point)); // 创建一个指向 Point 的指针
//Point* pPtr = new Point; C++可以这么写
p1->x = 10; // 使用 -> 访问成员 x
p1->y = 20; // 使用 -> 访问成员 y
cout << "Point: (" << p1->x << ", " << p1->y << ")" << endl; // 输出: Point: (10, 20)
free(p1); // 释放内存
//delete p1; C++可以这么写
3. 区分 &
和 *
-
&
运算符:- 主要用于获取变量的地址(取地址运算符)。
- 例如:
int* p = &a;
表示将变量a
的地址赋给指针p
。
-
*
运算符:- 主要用于指针的声明和解引用(取值运算符)。
- 在声明中,
int* p
表示p
是一个指向int
类型的指针。 - 在解引用时,
*p
表示访问指针p
所指向的内存地址中的值。
示例:
int a = 10;
int* p = &a; // & 用于获取 a 的地址
cout << *p; // * 用于解引用,输出 10
#include<bits/stdc++.h>
using namespace std;
// 定义节点结构体,包含一个整数和一个指向下一个节点的指针
struct node {
int w; // 节点中存储的整数值
struct node *next; // 指向下一个节点的指针
};
typedef struct node Node; // 为结构体 node 定义别名 Node
Node* head; // 链表的头节点指针
Node* back; // 链表的尾节点指针,用于快速在链表尾部插入
int len = 0; // 链表的长度,动态记录节点数量
// 初始化链表,创建一个空的头节点
void ini() {
head = (Node* )malloc(sizeof(Node)); // 分配内存给头节点
back = head; // 初始化 back 指向头节点
head->next = NULL; // 头节点的 next 设为 NULL,表明链表为空
}
// 根据位置 k 查找第 k 个节点
Node* find(int k) {
Node* temp = head; // 从头节点开始遍历
for (int i = 1; i <= k; i++) { // 移动到第 k 个节点
temp = temp->next;
}
return temp; // 返回第 k 个节点的指针
}
// 在节点 k 之后插入一个新节点,节点值为 x
void insert(Node* k, int x) {
Node* temp = (Node* )malloc(sizeof(Node)); // 分配新节点的内存
temp->w = x; // 将值 x 存入新节点
temp->next = k->next; // 新节点的 next 指向 k 的下一个节点
k->next = temp; // 将 k 的 next 指向新节点
if (k == back) back = temp; // 如果插入的是最后一个节点,更新 back
}
// 删除节点 k 的下一个节点
void deleteNode(Node* k) {
Node* temp = k->next; // 暂存要删除的节点
k->next = k->next->next; // 跳过被删除的节点,直接链接到下一个节点
free(temp); // 释放被删除节点的内存
}
int main() {
int n;
cin >> n; // 读取初始链表长度 n
ini(); // 初始化链表
for (int i = 1; i <= n; i++) {
int x;
cin >> x; // 读取每个节点的值
insert(back, x); // 在链表尾部插入节点
len++; // 更新链表长度
}
int m;
cin >> m; // 读取操作次数 m
while (m--) {
int op;
cin >> op; // 读取操作类型
if (op == 0) { // 插入操作
int k, d;
cin >> k >> d; // 读取插入位置 k 和插入的值 d
if (k <= 0 || k > len) continue; // 边界条件检查,跳过非法位置
insert(find(k), d); // 在第 k 个节点之后插入值为 d 的新节点
len++; // 更新链表长度
} else { // 删除操作
int k;
cin >> k; // 读取删除位置 k
if (k <= 0 || k > len) continue; // 边界条件检查,跳过非法位置
deleteNode(find(k - 1)); // 删除第 k 个节点
len--; // 更新链表长度
}
}
// 打印并释放链表中所有节点的内存
while (head->next != NULL) {
cout << head->next->w << " "; // 打印当前节点的值
Node* temp = head->next; // 暂存当前节点的指针
head->next = head->next->next; // 跳过当前节点,指向下一个节点
free(temp); // 释放当前节点的内存
}
return 0;
}
单链表——单链表的定义及基本操作(初始化、头插法尾插法建表、查找、插入、删除、判空等)_带头结点的单链表的元素的创建、查找、插入、删除等基本操作-CSDN博客
7-2矩阵运算
#include<bits/stdc++.h>
using namespace std;
bool check(int i,int j,int n){
if(i+j==n+1) return 0;//副对角线
if(j==n||i==n) return 0;//最后一列 最后一行
return 1;
}
int main(){
int n,ans=0;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x;
cin>>x;
if(check(i,j,n)){
ans+=x;
}
}
}
cout<<ans<<endl;
return 0;
}
7-3 删除重复字符
注意!输入空格!!!
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<char> v;
set<char> s;
char c;
while((c=getchar())!='\n'){
if(!s.count(c)){//查看原集合中是否存在,即之前是否出现过
s.insert(c);
v.push_back(c);
}
}
sort(v.begin(),v.end());//排序
for(char i:v){
cout<<i;
}
cout<<endl;
return 0;
}
字符不会超过128(ASCII码),开桶
#include<bits/stdc++.h>
using namespace std;
int tong[200];
int main(){
char c;
memset(tong,0,sizeof(tong));
while((c=getchar())!='\n'){
tong[(int)c]++;
}
for(int i=0;i<128;i++){
if(tong[i]){
cout<<(char)(i);
}
}
return 0;
}
C++常用STL
- vector 动态数组
- stack 栈
- queue 队列
- deque 双端队列
- priority_queue 优先队列
- map 映射(键值对)
- set 集合
7-4 统计字符出现次数
ASCII(American Standard Code for Information Interchange)码表是用于表示文本字符的标准编码系统。它为每个字符分配了一个唯一的整数值,以便计算机能够在不同设备之间交换文本数据。ASCII码表最初设计用于表示英文字符,但后来扩展了其他符号。
一共有128个字符,开桶即可。
#include<bits/stdc++.h>
using namespace std;
int cnt[200];
int main(){
char c;
while((c=getchar())!='\n'){
cnt[(int)c]++;
}
c=getchar();//小心空格,再次提醒
cout<<cnt[(int)c]<<endl;
return 0;
}
补录
//getchar() 返回的是读取的字符的 ASCII 值
while((c=getchar())!='\n'){
cnt[(int)c]++;
}
//这样写是可以的
while(scanf("%c", &c) && c != '\n') {
cnt[(int)c]++;
}
//scanf("%c", &c) 返回的是读取成功的项数,而不是读取的字符值,因此直接将它与 '\n' 进行比较是错误的
//故这样写是错误的ERROR
//scanf和printf本身也是一个函数,可以自己去了解
while(scanf("%c", &c) != '\n') {
}
}