当前位置: 首页 > news >正文

机试指南

文章目录

  • 零、绪论和IDE安装
    • int取值范围
    • 常犯的编程小错误
  • 一、枚举和模拟 (暴力求解)
    • (一) 枚举
      • 1.Reverse函数 求 反序数
      • 2.程序出错的原因
        • 1.编译错误 (compile):基本语法错误
        • 2.链接错误 (link):函数名写错了
        • 3.运行错误 (run):结果与预期不符,断点调试 [打断点,看监视]
      • 3.编程规范
        • 1.判断时,固定值写左边
        • 2.不要省略大括号
      • 4.命名规范
        • 1.变量命名规范
    • (二) 模拟
      • Ⅰ.图案问题:二维数组 + 找数字规律
        • 1.不确定数量的输入 while(scanf("%d",&n) != EOF){ }
        • 2.作用域
        • 3.机试对字符串的处理
          • 1.处理输入、输出:C风格字符串(字符数组):char str[1000]
          • 2.处理更复杂问题:C++风格字符串:string
        • 4.二维数组
        • 5.OJ问题
      • Ⅱ.日期问题
        • 1.闰年问题
        • 2.用空间换时间
        • 3.打印日期用printf,比cout方便
        • 4.map 映射
      • Ⅲ.其他模拟问题
  • 二、排序与查找
    • (一) 排序
      • 1.sort函数:sort(first,last,comp)
      • 2.C语言数组
      • 3.设计排序的规则:设计比较和交换的条件
      • 4.C++函数重载:同一个函数名,有不同的参数列表
      • 5.机试考试最重要的事情:能把你曾经做过的题目,满分地做出来
    • (二) 查找
      • 1.顺序查找(Liner Search)
        • 时间复杂度、空间复杂度
      • 2.二分查找(Binary Search)
      • 3.用map解决查找问题
        • 指针迭代器 iterator
  • 三、字符串
    • C字符数组:char arr[100] —— 输入输出
    • C++字符串:string —— 其他复杂操作
  • 四、线性数据结构
    • 1.向量 vector
    • 2.队列 queue
    • 3.栈 stack
  • 五、递归与分治
    • 递归与分治的关系
    • (一)、递归
      • 函数
      • 递归
    • (二)、分治
  • 六、非线性数据结构
    • 内存空间
      • 堆 (自由存储区)
    • 指针和引用
      • 指针(间接访问 值传递)
      • 引用(引用传递)
    • 1.二叉树
      • 二叉树的遍历
        • 层次遍历:队列
        • 递归遍历:前中后序遍历
      • 重建二叉树,并遍历
    • 2.二叉排序树 BST
    • 3.优先队列 priority_queue(堆 heap)
      • 优先队列模板 STL-priority_queue
      • 优先队列的应用
        • 1.顺序问题
          • 运算符重载
        • 2.哈夫曼树
    • 4.散列表 map
      • 映射 map
      • unorder_map
  • 七、搜索
    • BFS 广度优先搜索
      • 打表
    • DFS 深度优先搜索
      • 剪枝算法

零、绪论和IDE安装

1.安装IDE:clion或vs
新手不要直接在clion上写代码,要在强大的IDE(集成开发环境)中练习,能方便的找出低级错误。
在IDE上通过后,再把代码复制到OJ中。

2.OJ的运行原理:OJ不会直接评判代码,而是用测试用例来测试你的输出结果是否与它的答案相符。如此便能在某些情况下“作弊”。
若OJ中某个测试用例超时,可以提前准备好答案,以便通过用例。例如,“打表”。

3.机试需要的函数:输入(scanf 或 cin)、输出(printf 或 cout)、读取一行(fgets 或 cin.getline)
机试考察的数据结构:数组、链表、二叉树
机试需要的算法:枚举、模拟、递归、分治、搜索

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

会50%、会70%和会90%都是零分。要会,就要100%会。要么满分,要么零分!
练精一道题,胜于浅尝辄止10道题!


int取值范围

int的取值范围为:-231 -231-1 ,即:-2147483648 - 2147483647
注意题目要求的n的范围,判断f(n)是否会超过int的取值范围。若超过,则需要换成float或double或long long int或unsigned int。



常犯的编程小错误

1.问题:等价条件判断是 == ,写成了 =
情况:不好定位。段错误,且半天没看出问题,逻辑都是对的。最后找助教才帮忙看出来,花了十几分钟。尴尬。
解决:遵守编程规范,在写等价判断时,值写在左边,变量写在右边。 这样即使把==写成了=,也会是编译错误,直接报语法错误,好定位。



一、枚举和模拟 (暴力求解)

(一) 枚举

循环 + if + printf

1.Reverse函数 求 反序数

int Reverse(int n){ //求反序数的Reverse函数int remain;//每次的余数int reverse = 0;while(n != 0){remain = n%10;n = n/10;reverse = reverse*10 + remain;}return reverse;
}



2.程序出错的原因

前两步统称构建(build)

1.编译错误 (compile):基本语法错误

1.定位第一个编译错误,根据行号、列号、提示,去解决第一个编译错误。
编译错误只看第一个错误。因为解决一个问题可能就会解决一片编译错误。


2.链接错误 (link):函数名写错了

编译通过,说明基本的语法没有错误。
链接错误,并不提示链接错误的位置。一般就是函数名字写错了。


3.运行错误 (run):结果与预期不符,断点调试 [打断点,看监视]

运行时错误,构建(build)成功,即编译、链接都通过,但结果与预期不符。
运行错误也不会提示哪里有问题,这就需要通过打断点来进行断点调试了。

在这里插入图片描述


3.编程规范

1.判断时,固定值写左边

防止 if(n==0) 漏写为 if(n=0),导致死循环。而且这不是编译错误,检查不出来。
要写成if(0 == n),把固定值写左边。这样,如果漏写为 if( 0 =n)是不符合语法的,将错误提前到了编译阶段。
最简单的错误就是编译错误(语法错误)


2.不要省略大括号

虽然有些if里面只有一句话,可以省略花括号。但是对于企业级的项目来说,if里经常可能会添加新语句,而忘记花括号。对于这种经常变动的代码,务必全都加上大括号(即使只有一行),以防日后又增又删的调试。
即使你自己注意到了,难免后续接手的程序员不会忘记if里又加了几行时忘记使用花括号,而且这里加了没有调试,最终bug,花了半天时间才找到是因为这里if忘记加花括号了。
同时,维护别人写的代码时也要注意,在向单行循环体里加语句时,检查它是否有大括号


4.命名规范

1.变量命名规范

①外层循环使用不常见的变量名,减少内外层冲突的可能性
在这里插入图片描述

②类名的首字母大写。(类包括struct、class)




(二) 模拟

Ⅰ.图案问题:二维数组 + 找数字规律

在这里插入图片描述


1.不确定数量的输入 while(scanf(“%d”,&n) != EOF){ }

//输入n,然后输入n个数
int n;
int arr[101];
while (scanf("%d",&n) != EOF){for(int i=0;i<n;++i){scanf("%d",&arr[i]);}
}

注意:输入一串数据后,要先按Enter换行,再按Crtl+D。不换行则这一行数据没有输入缓冲区。

输入EOF:
①clion/gcc/clung:crtl+d
②vs:crtl+c


2.作用域

放在花括号内部的变量,生命周期只能在花括号里。
有时候有的变量需要设在全局,或者函数外部,才能被调用。


3.机试对字符串的处理

1.处理输入、输出:C风格字符串(字符数组):char str[1000]

C风格的字符串,本质是字符数组,以\0结尾。

char str[1000];//初始化
scanf("%s",str);//输入(字符串的输出不需要加&)
printf("%s\n",str);//输出

易错,%c注意要空格
在这里插入图片描述


2.处理更复杂问题:C++风格字符串:string
#include <string>
using namespace std;

①初始化:string str1 = "hello";
②连接:str1 = str1 + "world";
③下标访问:str1[0] //为h
④求长度:str1.length()
⑤判断相等:str1 == "hello"
⑥比较字典序:str1 > "abandon"
⑦从C++风格字符串转到C风格字符串:str1.c_str()
⑧删除最后一个字符:pop_back()


4.二维数组

char pat[80][80]={0};//定义二维数组并初始化,长度固定

5.OJ问题

在这里插入图片描述



Ⅱ.日期问题

1.闰年问题

bool isLeap = (year%400==0)  || (year%100!=0 && year%4==0);//true是闰年

2.用空间换时间

辅助数组

int mday[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

3.打印日期用printf,比cout方便

%d:打印数字
%4d:打印数字,至少4个位置宽,不足则用空格填充
%04d:打印数字,至少4个位置宽,不足则用0填充
在这里插入图片描述

cout的运行效率、格式控制,不如printf


4.map 映射

#include <map>
using namespace std;

map举例:

#include <cstdio>
#include <string>
#include <map>
using namespace std;int main(){//键 key --> 值 value//<键的类型,值的类型>map<string,string> myMap = {{"Caixukun","ikun"},{"Wuyifan","meigeni"}};char str[1000];scanf("%s",&str);string name = str;printf("%s的粉丝被称为%s",name.c_str(),myMap[name].c_str());
}



Ⅲ.其他模拟问题

1.剩余的树
2.手机键盘




二、排序与查找

(一) 排序

1.sort函数:sort(first,last,comp)

C++引入了基于快速排序的排序函数:sort()
sort(first,last,comp)函数的三个参数:①first为待排序序列起始地址 ②last为结束地址 ③comp为排序方式,不填写默认为升序排序。

#include <algorithm>
using namespace std;

左闭右开 [arr,arr+n),尾后
在这里插入图片描述



例1:对n个数进行排序

样例输入:
4
1 4 3 2

样例输出:
1 2 3 4

#include <cstdio>
#include <algorithm>
using namespace std;int main(){int n;int arr[101];scanf("%d",&n);for(int i=0;i<n;++i){scanf("%d",&arr[i]);//&arr[i] 和 arr+i 等价}sort(arr,arr+n);//排序for(int i=0;i<n;++i){printf("%d ",arr[i]);}printf("\n");
}


2.C语言数组

1.arr[i]是元素
2.arr是0号元素的地址。arr+i是i号元素的地址。
即,C语言数组的数组名,可以当地址/指针来使用。&arr[i] 和 arr+i 等价


3.设计排序的规则:设计比较和交换的条件

不发生交换,返回真


4.C++函数重载:同一个函数名,有不同的参数列表

比较的题目,重点就是设计bool comp(int lhs,int rhs)函数。//不发生交换时为真


5.机试考试最重要的事情:能把你曾经做过的题目,满分地做出来

最重要的不是把所有题目都写了个差不多,没用,差一点就是零分。要么满分要么零分。
最重要的是,把你曾经做过的题目,满分地做出来。
泥鳅老师:你就算是天纵奇才,也不可能在机试的时候把你从来没做过的题目做出来。就是一个熟练度的问题。



(二) 查找

1.顺序查找(Liner Search)

顺序查找的问题:效率不够高。
n个元素,顺序查找,时间复杂度为O(n²)。若数据量规模n在105,则会OJ超时。需要采取一些策略降低时间复杂度。


时间复杂度、空间复杂度

0.O()计数法:忽略常系数、忽略低阶项
1.时间复杂度:指令执行次数
2.空间复杂度:额外内存空间



2.二分查找(Binary Search)

要求先排序。数组有序后,才可使用二分查找。
基于比较的排序,时间复杂度最好为O(nlogn)
在这里插入图片描述
二分查找(需要排序)适用于:给定一份数据,要查很多次。
若每查一次,数据都改,那就用顺序查找,不需要排序。

mid = (left + right)/2;
left = mid + 1;    /收缩区间,注意 +1 -1,避免二分查找死循环。
right = mid - 1;



3.用map解决查找问题

map的底层:二叉搜索树(BST)。
①在Windows下,会进一步优化为:平衡二叉树(AVL树)
②在Linux下,会进一步优化为:红黑树

在这里插入图片描述


指针迭代器 iterator

findIndex.begin():第一个元素的指针
findIndex.end():最后一个元素的后面一个位置的指针,尾后指针
findIndex.find():查找某个元素的指针

if(findIndex.find(findNum) == findIndex.end()) /说明没有找到



三、字符串

C字符数组:char arr[100] —— 输入输出

1.字符数组
\0 作为正文结束的标志,也占一个空间

2.输入输出效率
printf和scanf的效率要优于cin和cout

3.读取一整行
fgets(字符数组名,sizeof(字符数组名),stdin)
fgets最后会读入换行符\n ,占一个空间(字符数组转string后,考虑用pop_back()干掉回车)
在这里插入图片描述

  1. getchar() 吃掉回车



C++字符串:string —— 其他复杂操作

1.头文件

#include <string>
using namespace std;

2.获取长度/大小:
string str;
str.length();
str.size();

printf("length of str = %u\n",str.size());

3.下标访问元素
str[i](i从0开始)

for(unsigned int i = 0;i < str.size(); ++i){printf("%c\n",str[i]);
}

4.(字符串的)迭代器访问元素

for(string::iterator it = str.beign(); it != str.end(); ++it){//++it 更改迭代器的指向,到下一个元素printf("%c\n", *it); // &取地址, *取内容
}

在这里插入图片描述


5.连接:字符串连接/拼接
+ (只针对C++风格字符串string类型,C风格字符数组禁止相加)

string str = buf;
str = str + "world";

6.删除 erase(下标)

str.erase(str.size()-1); //删除最后一个元素,即\n

7.清空 clear()

str.clear();

8.查询字符或字符子串的下标 .find(内容)
find("字符串")
find(变量名)
在这里插入图片描述

9.取字串 .substr(起始下标,长度)
若要切到尾为止,则只写一个参数:起始下标,不用写长度。

10.删除最后一个字符:pop_back()



四、线性数据结构

1.当定义的数组特别大,达到1千万时,不能定义在函数内部,会崩溃。栈比较小,但快。
要定义在全局位置,数据段中。
【局部大数组会崩溃,全局大数组不会崩溃】
在这里插入图片描述

2.标准模板库STL


1.向量 vector

vector是动态数组,长度可改变。 vector<int> vec;//创建空向量,长度为0
普通静态数组长度是固定不变的。int arr[100];//创建长度为100的静态数组

1.头文件

#include <vector>
using namespace std;

2.声明向量

vector<int> vec;//长度为0

3.赋初值

vector<int> vec2 {1,2,3};

4.申请一定空间的向量,所有元素初值默认为0

vector<int> vec3(10000);

※5.尾部插入:尾部扩容 push_back(元素) 。效率最高,插入n个为O(n),插入1个为O(1)。

vec.push_back(1);//vec[0]=1
vec.push_back(3);//vec[1]=3

※6.尾部删除:弹出尾部元素 pop_back()

vec.pop_back();

※7.下标访问

vec[i] //下标>=n时,数组越界

8.长度计算

vec.size();

9.两种遍历方法
①下标遍历

for(unsigned int i = 0; i < vec.size(); ++i){printf("vec[%d] = %d\n",i,vec[i]);
}

②迭代器遍历

for(vector<int>::iterator it = vec.begin(); it != vec.end(); ++it){printf("vec[] = %d\n",*it);
}

10.随机位置的插入:insert(位置,元素)

vector<int>::iterator it1 = vec.begin()+1;//迭代器指针指向vector的第二个位置
vec.insert(it1,3);//在vector第二个位置插入元素3

11.随机位置的删除:erase(位置);

vec.erase(vec.begin());//删除vector的第一个位置的元素

12.vector的实现原理
(1)vector的组成、申请空间(堆上)
vector是类类型,包括size容量、capacity内存大小、ptr首地址
首地址存放在栈上,但vector申请的内存空间在堆区上,堆区比栈区大,因此vector可申请空间比静态数组在栈上申请的空间可以大很多。【静态数组 - 栈 - 小空间。 vector - 堆- 大空间】

(2)vector的扩容机制
在这里插入图片描述



2.队列 queue

队列queue是受限制的线性表。只能在队尾加入,从队头入队

1.头文件

#include <queue>
using namespace std;queue<int> myQueue;

2.队尾入队 .push(变量名)

for(int i = 0;i <= 5;++i){myQueue.push(i);
}

3.队头出队 .pop()
4.判空 .empty()
5.队首元素 .front()

在这里插入图片描述



3.栈 stack

操作受限的线性表,只能一端进出。
栈,禁止操作的一端称为盲端。允许元素插入和删除的一端称为栈顶

1.头文件

#include <stack>
using namespace std;stack<typename> myStack//定义

2.方法
.size():栈大小
.push():压栈,将元素加入栈中
.top():获取栈顶内容
.pop():弹栈
.empty():判断栈是否为空

3.栈的应用
(1)逆序输出
(2)括号匹配
(3)表达式求值



五、递归与分治

递归与分治的关系

分治是一种思想,分而治之;递归是一种实现方法,函数调用自己。
分治思想可用递归来实现,也可以用其他方法来实现。递归作为一种方法,不止可以用于实现递归思想,也可以用来实现其他思想。
但总的来说,一般都用递归方法来实现分治的思想。故两者本不是同一纬度的概念,但是经常放在一起谈论。

常见的分治:求斐波那契数列、快速排序
常见的递归:求n的阶乘


(一)、递归

从函数到递归

①大问题→小问题,等价条件
②确定最小问题,即递归出口

函数

C语言编写的代码,以函数定义为单位。

call:把PC移到被调函数
ret:把PC移回主调函数

递归

1.在函数定义中调用本函数,叫做递归。

2.递归关注的两个点:
①大问题转化为小问题:规模n→规模n-1
②最小问题:递归出口



例题1:n的阶乘
例题2:汉诺塔



(二)、分治

①分解:大问题拆成小问题
②治理:找到等价条件,解决递归出口(最小问题)
③合并

在这里插入图片描述



例题1:斐波那契数列
例题网址:http://t.cn/Ai0K3tU5
题解:

#include <cstdio>int Fabonacci(int n){if(0==n || 1==n){return n;}else{return Fabonacci(n-1)+ Fabonacci(n-2);}
}int main(){int n;while(scanf("%d",&n) != EOF){//注意,输入多个数据后,要先Enter换行,再按crtl+Dif(n>=0){printf("%d\n",Fabonacci(n));}else{printf("error: n must >= 0\n");}}
}

例题2:二叉树
提交网址:http://t.cn/Ai0Ke6I0

#include <cstdio>int binaryTree(int m,int n){if(m>n){return 0;}else{return binaryTree(2*m,n) + binaryTree(2*m+1,n) + 1;}
}int main(){int m,n;while(scanf("%d %d",&m,&n) != EOF){if(m<=0 && n<=0){break;}printf("%d\n",binaryTree(m,n));}
}



六、非线性数据结构

内存空间

栈帧。当被调函数执行结束,栈帧上的变量也会被自动回收。

堆 (自由存储区)

new出来的,不会自动销毁。需要手动回收,否则会发生内存泄漏。
在这里插入图片描述

在这里插入图片描述



指针和引用

指针(间接访问 值传递)

1.* 取内容(间接访问)
在这里插入图片描述
2. &取地址

3.->运算符
若p为指针,则(*p).memberp->member等价
在这里插入图片描述


引用(引用传递)

引用,&x,&y就是给变量x,y起了个别名,并没有新开辟内存存储空间。这样,被调函数的参数列表(int &x, int &y)就可以直接引用传递给主函数中的变量x,y。因为&x &y与x y 享有同一个内存地址,会直接修改。



C++的两种传递方式:值传递、引用传递

例1:变量名-直接访问-值传递:在被调函数中无法修改主调函数中参数的内容。尽管变量名相同,但不是同一个地址

#include <cstdio>void swap1(int x,int y){int temp = x;x = y;y = temp;
}int main(){int x = 1 ,y = 2;swap1(x,y);
}

结果是,在swap1中x与y的值互换了,但main中的x与y的值不变。因为swap1中和main中的x、y的地址不同。


例2:指针-间接访问-值传递
在被调函数里改变主调函数中变量的内容:传指针(间接访问)
在普通函数中想要改变main函数中的值,要传指针。值才能透出去。

#include <cstdio>void swap2(int *px,int *py){int temp = *px;*px = *py;*py = temp;
}int main(){int x = 1 ,y = 2;int *px = &x;int *py = &y;swap2(px,py);
}

例3:引用-引用传递
对比例1,只修改了被调函数的参数列表,将int x,int y改为 int &x,int &y

#include <cstdio>void swap3(int &x,int &y){ int temp = x;x = y;y = temp;
}int main(){int x = 1 ,y = 2;swap3(x,y);
}

在这里插入图片描述




1.二叉树

在这里插入图片描述


二叉树的遍历

层次遍历:队列


递归遍历:前中后序遍历

重建二叉树,并遍历

在这里插入图片描述


例1:通过先序序列和中序序列建立二叉树,再输出后序遍历序列(华科复试上机真题)
提交网址:http://t.cn/AiKgDfLU

#include <cstdio>
#include <string>
using namespace std;struct TreeNode{char data;TreeNode * leftChild;TreeNode * rightChild;
};TreeNode *rebuild(string preOrder,string inOrder){ //返回值为子树根结点的地址if(preOrder.size() == 0){return NULL;}else{//从先序遍历确定根char rootdata = preOrder[0];TreeNode *pNewNode = new TreeNode;//二叉树结点指针pNewNode->data = rootdata;//用根位置切割中序int pos = inOrder.find(rootdata);//pos是根在中序序列中出现的下标pNewNode->leftChild = rebuild(preOrder.substr(1,pos),inOrder.substr(0,pos));pNewNode->rightChild = rebuild(preOrder.substr(pos+1),inOrder.substr(pos+1));return pNewNode;}
}void PostOrder(TreeNode * root){if(root == NULL){return;}PostOrder(root->leftChild);PostOrder(root->rightChild);printf("%c",root->data);return;
}int main(){char preOrder[30];char inOrder[30];while(scanf("%s%s",preOrder,inOrder) != EOF){TreeNode * root = rebuild(preOrder,inOrder);PostOrder(root);printf("\n");}
}

例2:根据有#的先序遍历序列,构建二叉树,并输出中序遍历序列 (清华复试上机真题)

哈哈哈



2.二叉排序树 BST

二叉排序树(二叉搜索树,二叉查找树 BST) 的建立

#include <cstdio>struct TreeNode{ //类类型/结构体类型int data;  //数据域TreeNode * leftChild; //左孩子指针TreeNode * rightChild;//右孩子指针
};void insertBST(TreeNode * &root,int data){//根,数据域TreeNode *pNewNode = new TreeNode;//申请一个空结点 pNewNodepNewNode->data = data;//主函数传进来的data,赋值给结点的数据域 pNewNode->datapNewNode->leftChild = NULL;//左孩子置为空pNewNode->rightChild = NULL;//右孩子置为空if(NULL == root){root = pNewNode; //若根结点为空,则让当前结点TreeNode * pNewNode 作为根结点 TreeNode * root}else{TreeNode * pPre = root;TreeNode * pCur;while(true){if(data < pPre->data){//新数据比根结点小,作为左孩子pCur = pPre->leftChild;if( NULL == pCur ){//左孩子为空   //判断条件是 == ,写成一个 = 了pPre->leftChild = pNewNode;break;}else{//左孩子结点不为空pPre = pCur;//当前结点作为新的根结点}}else{//新数据比根结点大,作为右孩子pCur = pPre->rightChild;if( NULL == pCur ){  //判断条件是 == ,写成一个 = 了pPre->rightChild = pNewNode;break;}else{pPre = pCur;}}}}
}int main(){TreeNode * root = NULL;int array[] = {2,3,5,1,4};for(int i = 0;i < 5; ++i){insertBST(root,array[i]);}}

例题1:华科 KY207 二叉排序树
提交网址:http://t.cn/Ai9PAkkv

#include <cstdio>struct TreeNode{ //类类型/结构体类型int data;  //数据域TreeNode * leftChild; //左孩子指针TreeNode * rightChild;//右孩子指针
};void insertBST(TreeNode * &root,int data){//根,数据域TreeNode *pNewNode = new TreeNode;//申请一个空结点 pNewNodepNewNode->data = data;//主函数传进来的data,赋值给结点的数据域 pNewNode->datapNewNode->leftChild = NULL;//左孩子置为空pNewNode->rightChild = NULL;//右孩子置为空if(NULL == root){root = pNewNode; //若根结点为空,则让当前结点TreeNode * pNewNode 作为根结点 TreeNode * rootprintf("-1\n");}else{TreeNode * pPre = root;TreeNode * pCur;while(true){if(data < pPre->data){//新数据比根结点小,作为左孩子pCur = pPre->leftChild;if( NULL == pCur ){//左孩子为空   //判断条件是 == ,写成一个 = 了pPre->leftChild = pNewNode;printf("%d\n",pPre->data);break;}else{//左孩子结点不为空pPre = pCur;//当前结点作为新的根结点}}else{//新数据比根结点大,作为右孩子pCur = pPre->rightChild;if( NULL == pCur ){  //判断条件是 == ,写成一个 = 了pPre->rightChild = pNewNode;printf("%d\n",pPre->data);break;}else{pPre = pCur;//当前结点作为新的根结点}}}}
}int main(){TreeNode * root = NULL;int n;scanf("%d",&n);for(int i = 0;i < n; ++i){int num;scanf("%d",&num);insertBST(root,num);}return 0;
}

例题2:浙大 判断是否为同一个二叉搜索树序列
提交网址:http://t.cn/Ai9PUJtK

在这里插入代码片



3.优先队列 priority_queue(堆 heap)

1.
优先队列不是队列(queue)而是堆(heap),是二叉堆(大根堆、小根堆),结构是完全二叉树,用数组保存。

2.大根堆
优先队列默认为大根堆。

priority_queue<typename>name;

3.小根堆 (重新定义优先队列)

priority_queue<typename,vector<typename>,greater<typename>>name

优先队列模板 STL-priority_queue

1.定义

#include <queue>
using namespace std;
priority_queue<typename>name;

2.状态
队空:是否为空 empty()
队长:元素个数 size()

3.增删元素
出队:插入元素 push()
入队:删除元素 pop()

4.元素访问
队首:只能访问优先级最高的元素 top()


优先队列的应用

1.顺序问题

运算符重载

重载小于运算符:operator <



2.哈夫曼树

1.求WPL(带权路径和)
①构建哈夫曼树,再求WPL:已掌握
②迭代式求WPL
在这里插入图片描述



例题1:哈夫曼树 (北邮复试上机真题)
提交网址:http://t.cn/AiCuGMki

#include <cstdio>
#include <queue>
using namespace std;int main(){priority_queue<int> pqueue;int n;scanf("%d",&n);for(int i = 0; i < n; ++i){int weight;scanf("%d",&weight);pqueue.push(-weight);}int res = 0; //存储带权路径长度和的中间结果while(pqueue.size()>1){int leaf1 = pqueue.top();pqueue.pop();int leaf2 = pqueue.top();pqueue.pop();res += leaf1 + leaf2;pqueue.push(leaf1+leaf2);}printf("%d\n",-res);return 0;
}



4.散列表 map

映射 map

1.map底层:红黑树 (RBT∈BST),
2.特点:所以map会自动排好序 (BST中序遍历是升序序列)。
3.map查找:时间复杂度 O(logn) (和二分查找相同的时间复杂度,但比二分查找需要更多的空间)
4.操作

(1)头文件

#include <map>
using namespace std;

定义

map<string,int> myMap;

初始化:

map<string,int> myMap = {{"Caixukun",1},{"Wuyifan",2},{"Liyifeng",3}
};

(2)插入键值对
insert()方法

myMap.insert(pair<string,int>("Wuyifan",2));

[]下标访问运算符

myMap["Caixukun"] = 1;

删除键值对:erase()

myMap.erase("Wuyifan");

读取键对应的值:


(3)判空:empty()
求长度(获取键值对个数):size()


(4)map的遍历:迭代器 iterator (迭代器是指向内部元素的指针)
①定义迭代器:map<string,int>::iterator it;
②第一个成员的位置:.begin()
③尾后位置:.end()
④迭代器指针后移:++it   (++it使得迭代器指针指向下一对键值对,unorder_map不支持此操作)
⑤键:it->first
⑥值:it->second

map<string,int>::iterator it;
for(it = myMap.begin();it != myMap.end();++it){printf("%s %d\n",it->first.c_str(),it->second);
}

(5)查找某个键是否存在:find()函数
在这里插入图片描述


例题1:查找学生信息 (清华大学复试上机题)
提交网址:http://t.cn/AiCuVIuY

#include <cstdio>
#include <string>
#include <map>
using namespace std;struct Student{string name;string gender;int age;
};int main(){int n;scanf("%d",&n);map<string,Student> InfoMap;for(int i = 0; i < n; ++i){char num[30];char name[30];char gender[30];int age;scanf("%s %s %s %d",num,name,gender,&age);//key stringstring numstr = num;//value StudentStudent student;student.name = name;student.gender = gender;student.age = age;InfoMap[numstr] = student;}int m;scanf("%d",&m);for(int i = 0; i < m; ++i){char num[30];scanf("%s",num);string numstr = num;if(InfoMap.find(numstr) != InfoMap.end()){//找到了printf("%s %s %s %d\n",numstr.c_str(),InfoMap[numstr].name.c_str(),InfoMap[numstr].gender.c_str(),InfoMap[numstr].age);}else{//学号没找到printf("No Answer!\n");//这里漏加换行符\n,导致格式错误了好几次。}}
}

例题2:魔咒词典 (浙大上机复试真题)
提交网址:http://t.cn/AiCufczt

#include <cstdio>
#include <string>
#include <map>
using namespace std;//魔咒词典  (采用 增量编辑法:即写一部分,测试一部分)
int main(){map<string,string> dict;while(true){char line[200];fgets(line,200,stdin);//输入一行string linestr = line;linestr.pop_back();//干掉回车,string最后一个字符为\nif("@END@" == linestr){break;}
//        printf("%s\n",linestr.c_str());int pos = linestr.find("]");string word = linestr.substr(0,pos+1);string info = linestr.substr(pos+2);
//        printf("word = %s, info = %s\n",word.c_str(),info.c_str());dict[word] = info;dict[info] = word;}int n;scanf("%d",&n);getchar();//吃掉回车 ※for(int i = 0 ; i < n; ++i){char line[200];fgets(line,200,stdin);string linestr = line;linestr.pop_back();if(dict.find(linestr) != dict.end()){//存在魔咒或功能if('[' == linestr[0]){//输入魔咒,查找功能printf("%s\n",dict[linestr].c_str());}else{//输入功能查找魔咒string charm = dict[linestr];//[xxxxxx],想办法去掉[]string charm_sub = charm.substr(1,charm.size()-2);//取子串,去掉了[]printf("%s\n",charm_sub.c_str());}}else{//不存在该魔咒或功能printf("what?\n");}}
}


unorder_map

1.底层:HashTable 散列表
2.unorder_map查找:时间复杂度O(1)
3.特点:①空间特别大 ②无序,不能遍历



七、搜索

搜索问题,就是带有限制的枚举问题。


BFS 广度优先搜索

BFS,Breadth First Search,广度优先搜索(宽度优先搜索)。
为了求最优解问题


例题1:Catch that Cow


例题2:Find the Multiple


打表

当OJ时限很小,且输入范围有限(1≤n≤200)


还是上文例题2:Find the Multiple,用打表法解决



DFS 深度优先搜索

DFS,Depth First Search,深度优先搜索。
为了知道问题是否有解,例如找迷宫出口


例题1:A Knight’s Journey
例题2:Square



剪枝算法

在深度优先遍历搜索过程中,可以通过放弃对某些不可能产生结果的子集的搜索,达到提高效率的目的。这样的技术称为剪枝。

相关文章:

机试指南

文章目录零、绪论和IDE安装int取值范围常犯的编程小错误一、枚举和模拟 (暴力求解)(一) 枚举1.Reverse函数 求 反序数2.程序出错的原因1.编译错误 (compile)&#xff1a;基本语法错误2.链接错误 (link)&#xff1a;函数名写错了3.运行错误 (run)&#xff1a;结果与预期不符&…...

Android CTA认证设定首选网络类型

需求 硬件只支持4G,过CTA认证时打网络电话,会出现3G网络的选择,会导致过不了,需要禁用3G网络选择功能。 Android 8.1.0 分析 可adb命令查看当前的网络类型 getprop | grep “network” 打印如下: [gsm.network.type]: [LTE,LTE] [ro.telephony.default_network]: [9] …...

Android 动态切换应用图标方案

经常听到大家讨论类似的需求&#xff0c;怀疑大厂是不是用了此方案&#xff0c;据我个人了解&#xff0c;多数头部 app 其实都是发版来更新节假日的 icon。当然本方案也是一种可选的方案&#xff0c;以前我也调研过&#xff0c;存在问题和作者所述差不多&#xff0c;此外原文链…...

SMART PLC斜坡函数功能块(梯形图代码)

斜坡函数Ramp的具体应用可以参看下面的文章链接: PID优化系列之给定值斜坡函数(PLC代码+Simulink仿真测试)_RXXW_Dor的博客-CSDN博客很多变频器里的工艺PID,都有"PID给定值变化时间"这个参数,这里的给定值变化时间我们可以利用斜坡函数实现,当然也可以利用PT1…...

不那么认真的linux复习

这是个不那么认真的linux总结&#xff0c;可能有一些错误 1、linuxkernel&#xff08;内核&#xff09;shell&#xff08;外壳&#xff09;fs&#xff08;文件系统&#xff09;pro/uti/tol&#xff08;应用程序&#xff09; 2、ls&#xff08;列出文件&#xff09; -a&#xf…...

Redis系列文章总纲

跟着老万学Redis 前言 从事开发工作这么久&#xff0c;很多核心技术其实都还只是局限在满足日常开发工作中的基础使用&#xff0c;并没有完整的总结研究。今年的目标之一是完成几个技术栈的系列博客&#xff0c;系统的总结一下知识体系&#xff0c;目前计划是从Redis开始。 Re…...

更新丨三大模块升级,助力高效交付商业项目!

功能更新&#xff01;本文将介绍最新升级的步进漫游、行业方案、VR漫游三个模块&#xff0c;让您更快更好的了解系统能力&#xff0c;为您带来更加便捷、高效的使用体验。步进漫游 离线导出步进式漫游系统&#xff0c;是基于全景图自动生成三维建模的解决方案&#xff0c;实现大…...

C++回顾(二)——const和引用

2.1 C中的const 2.1.1 C与C中const的比较 &#xff08;1&#xff09;C语言中的const C语言中 const修饰的变量是一个 常变量&#xff0c;本质还是变量&#xff0c;有自己的地址空间。 &#xff08;2&#xff09;C中的const 1、C中 const 变量声明的是一个真正的常量&#xff…...

MXNet中使用双向循环神经网络BiRNN对文本进行情感分类<改进版>

在上一节的情感分类当中&#xff0c;有些评论是负面的&#xff0c;但预测的结果是正面的&#xff0c;比如&#xff0c;"this movie was shit"这部电影是狗屎&#xff0c;很明显就是对这部电影极不友好的评价&#xff0c;属于负类评价&#xff0c;给出的却是positive。…...

DNS 域名解析

介绍域名 网域名称&#xff08;英语&#xff1a;Domain Name&#xff0c;简称&#xff1a;Domain&#xff09;&#xff0c;简称域名、网域。 域名是互联网上某一台计算机或计算机组的名称。 域名可以说是一个 IP 地址的代称&#xff0c;目的是为了便于记忆。例如&#xff0c…...

Spring MVC 源码- ViewResolver 组件

ViewResolver 组件ViewResolver 组件&#xff0c;视图解析器&#xff0c;根据视图名和国际化&#xff0c;获得最终的视图 View 对象回顾先来回顾一下在 DispatcherServlet 中处理请求的过程中哪里使用到 ViewResolver 组件&#xff0c;可以回到《一个请求响应的旅行过程》中的 …...

【Hello Linux】初识冯诺伊曼体系

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍冯诺伊曼体系 冯诺伊曼体系 冯诺伊曼体系结构的合理性 我们在Linux的第一篇博客中讲解了第一台计算机的发明是为了解决导弹的…...

mysql索引,主从多个核心主题去探索问题。

网上收集不错的优化方案 事务 mvcc 详讲 详讲 索引 索引概念 MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据 库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以在这些数 据…...

前端一面必会面试题(边面边更)

哪些情况会导致内存泄漏 以下四种情况会造成内存的泄漏&#xff1a; 意外的全局变量&#xff1a; 由于使用未声明的变量&#xff0c;而意外的创建了一个全局变量&#xff0c;而使这个变量一直留在内存中无法被回收。被遗忘的计时器或回调函数&#xff1a; 设置了 setInterval…...

【Hello Linux】初识操作系统

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍下操作系统的概念 操作系统 操作系统是什么&#xff1f; 操作系统是管理软硬件资源的软件 为什么要设计操作系统 为什么要设…...

完美的vue3动态渲染菜单路由全程

前言&#xff1a; 首先&#xff0c;我们需要知道&#xff0c;动态路由菜单并非一开始就写好的&#xff0c;而是用户登录之后获取的路由菜单再进行渲染&#xff0c;从而可以起到资源节约何最大程度的保护系统的安全性。 需要配合后端&#xff0c;如果后端的值不匹配&#xff0…...

2023年CDGA考试模拟题库(301-400)

2023年CDGA考试模拟题库(301-400) 300.无附加价值的信息通常也不会被删除,因为:[1分] A.它不应该被移除,所有数据都是有价值的 B.我们可能在以后的某个阶段需更这些信息 C.规程中不明确是否应该保留 D.数据是一种资产它很可能在未来被认为是有价值的 E.规程中不明确哪些是…...

Linux-常见命令

&#x1f69c;关注博主&#xff1a;翻斗花园代码手牛爷爷 &#x1f699;Gitee仓库&#xff1a;牛爷爷爱写代码 目录&#x1f692;xshell热键&#x1f697;Linux基本命令&#x1f697;ls指令&#x1f695;pwd指令&#x1f696;cd指令&#x1f68c;touch指令&#x1f68d;mkdir指…...

2.25测试对象分类

一.按照测试对象划分1.界面测试又称UI测试,按照界面的需求(一般是ui设计稿)和界面的设计规则,对我们软件界面所展示的全部内容进行测试和检查.对于非软件来说:颜色,大小,材质,整体是否美观对于软件来说:输入框,按钮,文字,图片...的尺寸,颜色,形状,整体适配,清晰度等等,2.可靠性…...

【Zabbix实战之部署篇】Zabbix客户端的安装部署方法

【Zabbix实战之部署篇】Zabbix客户端的安装部署方法 一、Zabbix-agent2介绍1.Zabbix-agent2简介2.Zabbix-agent2优点3.主动模式和被动模式二、环境规划1.Zabbix服务器部署链接2.IP规划三、配置客户端系统环境1.关闭selinux2.放行端口或关闭防火墙四、安装zabbix-agent21.下载za…...

【CSS】CSS 层叠样式表 ② ( CSS 引入方式 - 内嵌样式 )

文章目录一、CSS 引入方式 - 内嵌样式1、内嵌样式语法2、内嵌样式示例3、内嵌样式完整代码示例4、内嵌样式运行效果一、CSS 引入方式 - 内嵌样式 1、内嵌样式语法 CSS 内嵌样式 , 一般将 CSS 样式写在 HTML 的 head 标签中 ; CSS 内嵌样式 语法如下 : <head><style …...

MySQL事务与索引

MySQL事务与索引 一、事务 1、事务简介 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。事务处理可以用来维护数据库的完整性&#xff0c;保证成批的 SQL 语句要么全部执行&#xff0c;要么全部不执行。事务用来管理 insert,update,delete 语句 事务特性…...

【编程入门】应用市场(php版)

背景 前面已输出多个系列&#xff1a; 《十余种编程语言做个计算器》 《十余种编程语言写2048小游戏》 《17种编程语言10种排序算法》 《十余种编程语言写博客系统》 《十余种编程语言写云笔记》 《N种编程语言做个记事本》 目标 为编程初学者打造入门学习项目&#xff0c;使…...

文化:你所在的团队,有多少人敢讲真话?

你好&#xff0c;我是叶芊。 今天我们要讨论的话题是文化&#xff0c;说“文化”这个词你可能会觉得很虚&#xff0c;那我们换个词——“做事风格”&#xff0c;这就和你们团队平时的协作习惯密切相关了。 做事风格&#xff0c;往小了讲&#xff0c;会影响团队成员对开会的认知…...

Linux | 项目自动化构建工具 - make/Makefile

make / Makefile一、前言二、make/Makefile背景介绍1、Makefile是干什么的&#xff1f;2、make又是什么&#xff1f;三、demo实现【见见猪跑&#x1f416;】三、依赖关系与依赖方法1、概念理清2、感性理解【父与子】3、深层理解【程序的翻译环境 栈的原理】四、多学一招&#…...

Spring源码该如何阅读?十年架构师带来的Spring源码解析千万不要错过!

写在前面最近学习了一句话&#xff0c;感觉自己的世界瞬间明朗&#xff0c;不再那么紧张焦虑恐慌&#xff0c;同样推荐给大家&#xff0c;希望我们都终有所得。“如果一个人不是发自内心地想要做一件事情&#xff0c;那么&#xff0c;他是无法改变自己的人生的。” 同样这句话用…...

sonarqube 外部扫描器 go vet golangci-lint 无法导入问题

首先&#xff0c;请看[外部分析报告]各种语言的报告生成 go vet 2> govet-report.out#没有golangci-lint&#xff0c;我从网上找到了 golangci-lint run --out-format checkstyle ./... > golangci-lint-report.xml值得注意的是&#xff0c;貌似不支持目录&#xff0c;仅…...

Tesseract-OCR 控制台怎么使用

Tesseract-OCR 控制台是一个命令行工具&#xff0c;可以在 Windows、Linux、macOS 等操作系统中使用。下面是使用 Tesseract-OCR 控制台进行文字识别的基本步骤&#xff1a;安装 Tesseract-OCR&#xff1a;可以到 Tesseract-OCR 的官方网站&#xff08;https://github.com/tess…...

九龙证券|美股创年内最大周跌幅!美联储官员密集发声!波音重挫近5%

当地时刻2月24日&#xff0c;美股三大指数收盘明显跌落。道指跌1.02%&#xff0c;标普500指数跌1.05%&#xff0c;纳指跌1.69%。 大型科技股普跌&#xff0c;微软、亚马逊跌超2%。波音大跌4.8%&#xff0c;居道指跌幅榜首位&#xff0c;公司因机身部件有问题再次暂停向用户交付…...

C++014-C++字符串

文章目录C014-C字符串字符串目标char[]和stringchar[]char*string字符常量与字符串常量字符串的输入题目描述 字符串输出题目描述在线练习&#xff1a;总结C014-C字符串 在线练习&#xff1a; http://noi.openjudge.cn/ https://www.luogu.com.cn/ 字符串 目标 1、了解字符串…...