二叉树的顺序存储
//
// Created by W9067299 on 2023/10/10.
//
#include <iostream>//定义头文件
#include <stdlib.h>//定义头文件
#include <deque>//定义头文件
#include <vector>//定义头文件
#include <queue>//定义头文件
using namespace std;
const int MaxSize=1024;
typedef struct
{
int data[MaxSize]; // 存储树结点的数组
int BiTreeNum; // 二叉树的结点个数
}SqBiTree;
class tree{
public:
vector<int> data = vector<int>(MaxSize,0);
int BiTreeNum; // 二叉树的结点个数
};
//初始化树
void initTree(tree &T){
T.BiTreeNum=0;
}
//创建树
void createTree(tree &T,int n){
int ch;
cin>>ch;
if(ch == 0){
return;
}
else{
T.data[n] = ch;
T.BiTreeNum++;
cout<<"输入左子树值:"<<endl;
createTree(T, 2*n);
cout<<"输入右子树值:"<<endl;
createTree(T,(2*n+1));
}
}
void PreOrder_Traverse(tree T, int n)
{
if(T.data[n] == 0) {
cout << "空" << " ";
return;
}
else
{
cout<<T.data[n]<<" ";
PreOrder_Traverse(T, 2*n);
PreOrder_Traverse(T, (2*n+1));
}
}
void InOrder_Traverse(tree T, int n)
{
if(T.data[n] == 0) {
cout << "空" << " ";
return;
}
else
{
InOrder_Traverse(T, 2*n);
cout<<T.data[n]<<" ";
InOrder_Traverse(T, (2*n+1));
}
}
void PostOrder_Traverse(tree T, int n) {
if(T.data[n] == 0) {
cout << "空" << " ";
return;
}
else {
PostOrder_Traverse(T, 2 * n);
PostOrder_Traverse(T, (2 * n + 1));
cout<<T.data[n]<<" ";
}
}
//层序遍历 借助到队列
void cegxu_Treverse(tree T, int n) {
queue<int> m;
//根节点队
m.push(T.data[n]);
int j=n;
while (m.size()!=0){
int l=2*j;
int r=2*j+1;
if(T.data[l]!=0)
m.push(T.data[l]);
if(T.data[r]!=0)
m.push(T.data[r]);
cout<<m.front()<<" ";
m.pop();
j++;
}
}
int main(){
tree T;
cout<<"输入根节点的值:"<<endl;
initTree(T);
createTree(T,1);
cout<<"先序遍历为:"<<endl;
PreOrder_Traverse(T,1);
cout<<endl;
cout<<"层序遍历为:"<<endl;
cegxu_Treverse(T,1);
return 0;
}
链式存储
//
// Created by W9067299 on 2023/7/24.
//
#include <unordered_map>
#include "iostream"
#include "cstring"
#include "vector"
using namespace std;
class treenode{
public:
treenode(int i) : left(nullptr), right(nullptr){
value=i;
}
treenode *left;
treenode *right;
int value;
};
class tree{
public:
treenode *root;
int count=0;
//构件树 先构建根节点
treenode* create(){
treenode *node;
int temp;
cin>>temp;
if (temp==0){
node= nullptr;
} else {
count++;
node= new treenode(0);
node->value=temp;
node->left = create();
node->right = create();
}
return node;
}
//先序遍历
void preorder(treenode *r){
if(r!= nullptr){
cout<<r->value<<" ";
preorder(r->left);
preorder(r->right);
}
}
//根据先序和中序创建树
treenode* picreate(vector<int> pre,vector<int> inord){
/**
* 建立哈希索引
*/
for (int i = 0; i < pre.size(); ++i) {
pre_hash[i]= pre[i];
}
for (int i = 0; i < inord.size(); ++i) {
inord_hash[inord[i]]= i;
}
return build(0,inord.size()-1,0);
}
treenode* build(int left,int right,int root_index_pre){
if(left>right)
return nullptr;
treenode* root=new treenode(pre_hash[root_index_pre]);
int root_index_inorder=inord_hash[pre_hash[root_index_pre]];
int left_nodes=root_index_inorder-left;
root->left= build(left,root_index_inorder-1,root_index_pre+1);
//三个参数 最后一个是 就是先序遍历 前 左 右 定位到去除当前节点和左子树的节点
root->right= build(root_index_inorder+1,right,root_index_pre+left_nodes+1);
return root;
}
//销毁
void shanchu(treenode *r){
if(r!= nullptr){
preorder(r->left);
preorder(r->right);
delete r;
}
}
unordered_map<int,int> pre_hash;
unordered_map<int,int> inord_hash;
};
int main(){
tree mytree;
mytree.root=mytree.create();
mytree.preorder(mytree.root);
// mytree.shanchu(mytree.root);
cout<<mytree.count;
// mytree.root=mytree.picreate({1,2,3,4,6,5,7},{2,1,6,4,3,5,7});
// mytree.preorder(mytree.root);
return 0;
}
C++标准模板库函数STL
数组:vector
栈:stack
队列:queue
堆(优先队列):priority_queue
哈希表:unordered_set 键值哈希表:unordered_map
红黑树:set 键值红黑树:map
考研只需要掌握最高频的几个api就行,考研是考你算法基础的,不是考你怎么炫技api的,Java的api过于炫技也许就是它从考研官方语言中被剔除的原因,扎实的基本功虽然朴素且低调,反而却是最实用和华丽的,
好人做到底,送佛送到西,直接给大家把408考试需要掌握C或者C++的API总结出来。
结构体
// C
typedef struct {
int x;
int y;
}Point;
typedef struct point{ // point为标识
int x;
int y;
}Point; // Point为对象类型
// C++
struct Point {
int x, y;
Point(int _x, int _y): x(_x), y(_y) {}
};
数组:
#include <string.h> // 导入头文件
#include <iostream> // 导入头文件
#include <vector> // 导入头文件
#include <stdlib.h> // 导入头文件
using namespace std; // 声明命名空间
const int m = 50;
const int n = 100;
int main(){
//
int a[n]; //创建大小为n的数组, 下标范围[0,n-1]
memset(a, 0, sizeof(a)); // 初始化所有元素为0
a[5] = 1; //修改下标为5的元素值为1
// 二维数组
int g[m][n]; //创建大小为m*n的数组, m行n列,行下标范围[0,m-1],列下标范围[0,n-1],可用于创建邻接矩阵
memset(g, 0, sizeof(g)); // 初始化所有元素为0
g[5][4] = 1; //修改下标5行下标4列的元素值为1,邻接矩阵中结点0和结点1之间存在一条有向边,或者结点0和结点1之间有向边长度1
//简单使用vector
vector<int> c(7);
c[5]=1;
c.push_back(2);
//初始化一个特殊的数组
vector<int> v3(5,111);//构造一个空间大小为5,并且元素为5个(每个元素初始值为111)的vector
vector<int> v4(v3);//拷贝构造vector
//一维的遍历 记住这一个就行
for (int i = 0; i < v3.size(); ++i) {
cout<<v3[i]<<" ";
}
//二维数组
vector<vector<int>> nums(m ,vector<int>(n,1)); //m*n的二维vector,所有元素为0 如果后面只填了vector<int> (n)默认全部值为0
//不可以使用memset
//二维的遍历
for(int i = 0; i < nums.size(); i++){
for(int j = 0; j < nums[0].size(); j++){
cout<<nums[i][j]<<" ";
}
}
return 0;
}
重点 类中初始化为
class tree{
public:
vector<int> data = vector<int>(MaxSize,0);
int BiTreeNum; // 二叉树的结点个数
};
栈:
#include <stack> // 导入头文件
using namespace std; // 声明命名空间
stack<int> s; // 初始化一个空栈
s.push(1); // 入栈,向栈顶增加元素1
s.top(); // 返回当前栈顶元素值,注意在栈不为空的情况下进行
s.pop(); // 出栈,栈顶元素出栈,注意在栈不为空的情况下进行
s.empty(); // 返回当前栈是否为空
s.size(); // 返回当前栈的元素个数
队列:
#include <queue> // 导入头文件
using namespace std; // 声明命名空间
queue<int> q; // 初始化一个队列
q.push(1); // 入队,向队尾增加元素1
q.front(); // 返回当前队列头元素值,注意在队列不为空的情况下进行
q.pop(); // 出队,弹出队头元素
q.empty(); // 返回当前队列是否为空
q.size(); // 返回当前队列的元素个数
堆(优先队列):priority_queue
#include <queue> // 导入头文件
using namespace std; // 声明命名空间
// 大顶堆
priority_queue<int> max_heap;
priority_queue<int, vector<int>, less<int>> max_heap;
// 小顶堆
priority_queue<int, vector<int>, greater<int>> min_heap;
priority_queue<int> pq; // 初始化一个大顶堆
pq.push(1); // 向堆中插入一个元素
pq.top(); // 返回堆顶元素值
pq.pop(); // 移除堆顶元素
pq.empty(); // 返回当前堆是否为空
pq.size(); // 返回当前堆中元素个数
哈希表:unordered_set
#include <unordered_set> // 导入头文件
using namespace std; // 声明命名空间
unordered_set<int> s; // 创建哈希表
s.insert(1); // 向哈希表中插入元素1
s.count(1); // 返回哈希表中是否存在元素1
s.size(); // 返回哈希表中元素个数
键值哈希表:unordered_map
#include <unordered_map> // 导入头文件
using namespace std; // 声明命名空间
unordered_map<int, int> mp; // 创建键值哈希表,第一个类型为key类型,第二个类型为value类型
mp[1] = 10; // 设定key为1的value为10
mp[1]++; // 设定key为1的value增加1
mp.count(1); // 返回键值哈希表中是否存在键值为1的元素
mp[1]; // 获取key为1的value,如果不存在,会自动创建key为1,value为默认0
mp.size(); // 返回哈希表中元素个数
注:键key为char或者26个字母的哈希表建议用数组代替:
// C
int cnt[128]; // key为char类型
memset(cnt, 0, sizeof(cnt)); // 初始化所有key的value为0
cnt[c] = 1; // key为c的value设为1
cnt[c]; // 返回key为c的value
int cnt[26]; // key为26个字母
memset(cnt, 0, sizeof(cnt)); // 初始化所有key的value为0
cnt[c - 'a'] = 1; // key为小写字母c的value设为1
cnt[c - 'a']; // 返回key为小写字母c的value
// C++
vector<int>cnt(128); // key为char类型
cnt[c] = 1; // key为c的value设为1
cnt[c]; // 返回key为c的value
vector<int>cnt(26); // key为26个字母
cnt[c - 'a'] = 1; // key为小写字母c的value设为1
cnt[c - 'a']; // 返回key为小写字母c的value
红黑树:set
#include <set> // 导入头文件
using namespace std; // 声明命名空间
set<int> s; // 创建红黑树
s.insert(1); // 向红黑树中插入元素1
s.count(1); // 返回红黑树中是否存在元素1
s.size(); // 返回红黑树中元素个数
键值红黑树:map
#include <map> // 导入头文件
using namespace std; // 声明命名空间
map<int, int> mp; // 创建键值红黑树,第一个类型为key类型,第二个类型为value类型
mp[1] = 10; // 设定key为1的value为10
mp[1]++; // 设定key为1的value增加1
mp.count(1); // 返回键值红黑树中是否存在键值为1的元素
mp[1]; // 获取key为1的value,如果不存在,会自动创建key为1,value为默认0
mp.size(); // 返回红黑树中元素个数
数学
这个理论上不推荐使用,但是我列出的几个属于最简单的了,理论上不会扣分。
保险起见可以使用 if else 或者三目运算符。
#include <algorithm> // 导入头文件
using namespace std; // 声明命名空间
max(x, y); // 返回x和y中的最大值,注意x和y类型要相同
min(x, y); // 返回x和y中的最小值,注意x和y类型要相同
abs(x); // 返回x的绝对值
内存分配与回收
这个属于为了严谨,不写理论上不扣分。
// C
#include <stdlib.h> // 注:和C++混编时写为 #include <cstdlib>
typename *p=(typename*)malloc(sizeof(typename));
free(p);
// C++
#include <iostream>
using namespace std;
typename *p=new typename;
delete(p);