2021算法笔记Codeup、pat刷题记录
目录
《算法笔记》9.1小节——数据结构专题(2)->树与二叉树
《算法笔记》9.2小节——数据结构专题(2)->二叉树的遍历
Codeup
复原二叉树
#include<iostream>
#include<string>
using namespace std;
struct node {
char data;
node* lchild;
node* rchild;
};
string pre, in, post;
node* create(int preL, int preR, int inL, int inR) {
if (preR < preL) return NULL;
node* root = new node;
root->data = pre[preL];
int k;
for (k = inL;k < inR;++k) {
if (in[k] == pre[preL]) break;
}
int numLeft = k - inL;
root->lchild = create(preL + 1, preL + numLeft, inL, k - 1);
root->rchild = create(preL + numLeft + 1, preR, k + 1, inR);
return root;
}
void postOrder(node* root) {
if (root == NULL) return;
postOrder(root->lchild);
postOrder(root->rchild);
cout << root->data;
}
int main() {
while (cin >> pre >> in) {
int n = pre.size();
node* root = create(0, n - 1, 0, n - 1);
postOrder(root);
cout << endl;
}
return 0;
}
二叉树
用的完全二叉树的性质
#include<cstdio>
int get_ans(int n, int m) {
if (m <= n) {
int ans = 1;
return ans + get_ans(n, m * 2) + get_ans(n, m * 2 + 1);
}
return 0;
}
int main() {
int m, n;
while (scanf("%d %d", &m, &n), m != 0 && n != 0) {
printf("%d\n", get_ans(n, m));
}
return 0;
}
二叉树遍历
原题
二叉树遍历
#include<cstdio>
#include<cstring>
struct node {
char data;
node* lchild;
node* rchild;
};
char pre[110], len;
int i = 0;
node* create() {
if (pre[i] == '#') {
++i;
return NULL;
}
node* root = new node;
root->data = pre[i];
++i;
root->lchild = create();
root->rchild = create();
return root;
}
void inOrder(node* root) {
if (root == NULL) return;
inOrder(root->lchild);
printf("%c ", root->data);
inOrder(root->rchild);
}
int main() {
while (scanf("%s", pre) != EOF) {
i = 0;
len = strlen(pre);
node* root = create();
inOrder(root);
printf("\n");
}
return 0;
}
配套实战指南
PAT A1020 Tree Traversals
#include<cstdio>
#include<queue>
using namespace std;
const int maxn = 35;
struct node {
int data;
node* lchild;
node* rchild;
};
int in[maxn], post[maxn];
int n;
node* create(int postL, int postR, int inL, int inR) {
if (postL > postR) return NULL;
node* root = new node;
root->data = post[postR];
int k;
for (k = inR;k >= inL;--k) {//这里是in
if (in[k] == post[postR]) break;
}
int numLeft = k - inL;
root->lchild = create(postL, postL + numLeft - 1, inL, k - 1);
root->rchild = create(postL + numLeft, postR - 1, k + 1, inR);//记得这里要postR-1
return root;
}
int num = 0;
void BFS(node* root) {
queue<node*> qu;
qu.push(root);
while (!qu.empty()) {
node* top = qu.front();
qu.pop();
if (num > 0) printf(" ");
printf("%d", top->data);
++num;
if (top->lchild) qu.push(top->lchild);
if (top->rchild) qu.push(top->rchild);
}
}
int main() {
scanf("%d", &n);
for (int i = 0;i < n;++i) scanf("%d", &post[i]);
for (int i = 0;i < n;++i) scanf("%d", &in[i]);
node* root = create(0, n - 1, 0, n - 1);
BFS(root);
return 0;
}
1086 Tree Traversals Again
先序建树,思路是Push时建立结点,Pop时返回NULL,剩余的结点都填充NULL;
答案的思路好像是Push的次序是先序遍历的顺序,Pop的次序则是中序遍历的顺序,通过先序遍历+中序遍历唯一确定二叉树。
#include<cstdio>
#include<cstring>
struct node {
int data;
node* lchild;
node* rchild;
};
int n, count = 0;
char str[5];
node* create() {//输入时进行递归建树
node* root = new node;
getchar();
if (count++ < 2 * n) scanf("%s", str);//2N次
if (strcmp(str, "Push") == 0) {
int temp;
scanf("%d", &temp);
root->data = temp;
root->lchild = create();
root->rchild = create();
return root;
}
else {
return NULL;
}
}
int cnt = 0;
void postOrder(node* root) {//后序输出
if (root == NULL) return;
postOrder(root->lchild);
postOrder(root->rchild);
if (cnt > 0) printf(" ");
printf("%d", root->data);
++cnt;
}
int main() {
scanf("%d", &n);
node* root = create();
postOrder(root);
printf("\n");
return 0;
}
前序中序建树
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 50;
struct node {
int data;
node* lchild;
node* rchild;
};
int pre[maxn], in[maxn];
int n;
node* create(int preL, int preR, int inL, int inR) {
if (preL > preR) return NULL;
node* root = new node;
root->data = pre[preL];
int k;
for (k = inL;k <= inR;++k) {
if (in[k] == pre[preL]) break;
}
int numLeft = k - inL;
root->lchild = create(preL + 1, preL + numLeft, inL, k - 1);
root->rchild = create(preL + numLeft + 1, preR, k + 1, inR);
return root;
}
int num = 0;
void postOrder(node* root) {
if (root == NULL) return;
postOrder(root->lchild);
postOrder(root->rchild);
if (num > 0) printf(" ");
printf("%d", root->data);
++num;
}
int main() {
scanf("%d", &n);
char str[5];
stack<int> st;
int x, preIndex = 0, inIndex = 0;
for (int i = 0;i < 2 * n;++i) {
scanf("%s", str);
if (strcmp(str, "Push") == 0) {
scanf("%d", &x);
pre[preIndex++] = x;
st.push(x);
}
else {
in[inIndex++] = st.top();
st.pop();
}
}
node* root = create(0, n - 1, 0, n - 1);
postOrder(root);
return 0;
}
PAT A1102 Invert a Binary Tree
根据题目给予的编号关系想到使用静态二叉树。
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 15;
struct node {
int data;
int lchild;
int rchild;
node() {
lchild = rchild = -1;
}
}Node[maxn];
bool hashTable[maxn] = { false };//标记根节点
int n, root;
void LayerOrder() {
int cnt = 0;
queue<int> qu;
qu.push(root);
while (!qu.empty()) {
int top = qu.front();
qu.pop();
if (cnt > 0) printf(" ");
printf("%d", top);
++cnt;
if (Node[top].lchild != -1) qu.push(Node[top].lchild);
if (Node[top].rchild != -1) qu.push(Node[top].rchild);
}
printf("\n");
}
int time = 0;
void inOrder(int root) {
if (root == -1) return;
inOrder(Node[root].lchild);
if (time > 0) printf(" ");
printf("%d", Node[root].data);
time++;
inOrder(Node[root].rchild);
}
int main() {
scanf("%d", &n);
for (int i = 0;i < n;++i) {
char a, b;
scanf("%*c%c %c", &a, &b);
Node[i].data = i;
if (a >= '0' && a <= '9') {
int temp = a - '0';
Node[i].lchild = temp;
hashTable[temp] = true;
}
if (b >= '0' && b <= '9') {
int temp = b - '0';
Node[i].rchild = temp;
hashTable[temp] = true;
}
}
for (int i = 0;i < n;++i) {//确定根节点,同时反转二叉树
if (hashTable[i] != true) {
root = i;
}
swap(Node[i].lchild, Node[i].rchild);//反转
}
LayerOrder();
inOrder(root);
return 0;
}
《算法笔记》9.3小节——数据结构专题(2)->树的遍历
Codeup
树查找
利用完全二叉树的性质
#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
int pow(int x, int p) {
int ans = 1;
for (int i = 0;i < p;++i) {
ans *= x;
}
return ans;
}
int main() {
vector<int> node;
int n, d;
while (scanf("%d", &n), n) {
node.push_back(0);
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &temp);
node.push_back(temp);
}
scanf("%d", &d);
int s = pow(2, d - 1);
int t = pow(2, d);
if (s > n) {
printf("EMPTY\n");
node.clear();//这里注意要clear
continue;
}
for (int i = s;i < min(t, n + 1);++i) {
if (i > s) printf(" ");
printf("%d", node[i]);
}
printf("\n");
node.clear();
}
return 0;
}
树的高度
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
struct node {
vector<int> child;
int height;
}Node[110];
int BFS() {
int height;
queue<node> qu;
qu.push(Node[1]);
while (!qu.empty()) {
node top = qu.front();
height = top.height;
qu.pop();
if (top.child.size() != 0) {
for (int i = 0;i < top.child.size();++i) {
Node[top.child[i]].height = top.height + 1;
qu.push(Node[top.child[i]]);
}
}
}
return height;
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
for (int i = 1;i < n;++i) {
int a, b;
scanf("%d %d", &a, &b);
Node[a].child.push_back(b);
}
Node[1].height = 1;
printf("%d\n", BFS());
}
return 0;
}
配套实战指南
PAT A1079 Total Sales of Supply Chain
题目有点难看懂,其他很常规
BFS解法
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 100010;
struct node {
double price;
int amount;//销售数量
vector<int> child;
node() {
amount = 0;
child.clear();
}
}Node[maxn];
int n;
double p, r;
double sum = 0;
int BFS() {
queue<int> qu;
qu.push(0);
while (!qu.empty()) {
int top = qu.front();
qu.pop();
if (Node[top].child.size() > 0) {
for (int i = 0;i < Node[top].child.size();++i) {
int c = Node[top].child[i];
Node[c].price = Node[top].price * r;
qu.push(c);
}
}
else {
sum += Node[top].amount * Node[top].price;
}
}
return sum;
}
int main() {
scanf("%d %lf %lf", &n, &p, &r);
r = r / 100 + 1;
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &temp);
if (temp == 0) {
scanf("%d", &Node[i].amount);
}
else {
for (int j = 0;j < temp;++j) {
int child;
scanf("%d", &child);
Node[i].child.push_back(child);
}
}
}
Node[0].price = p;
BFS();
printf("%.1f", sum);
return 0;
}
DFS解法
void DFS(int index){
if(Node[index].child.size()==0){
sum+=Node[index].amount*Node[index].price;
return;
}
for(int i=0;i<Node[index].child.size();++i){
Node[Node[index].child[i]].price=Node[index].price*r;
DFS(Node[index].child[i]);
}
}
PAT A1090 Highest Price in Supply Chain
DFS
#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
const int maxn = 100010;
vector<int> child[maxn];
int n, maxdepth = 0, cnt = 0;
double p, r;
void DFS(int index, int depth, int& maxdepth) {
if (depth > maxdepth) {
maxdepth = depth;
cnt = 1;
}
else if (depth == maxdepth) ++cnt;
if (child[index].size() > 0) {
for (int i = 0;i < child[index].size();++i) {
DFS(child[index][i], depth + 1, maxdepth);
}
}
else {
return;
}
}
int main() {
scanf("%d %lf %lf", &n, &p, &r);
r /= 100;
int root;
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &temp);
if (temp == -1) root = i;
else {
child[temp].push_back(i);
}
}
DFS(root, 0, maxdepth);
printf("%.2f %d\n", p * pow(1 + r, maxdepth), cnt);
return 0;
}
因为使用BFS要在struct里面放入height才能实现,所以不太想写-。-
PAT A1094 The Largest Generation
DFS
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 110;
vector<int> child[maxn];
int n, m, hashTable[maxn] = { 0 }, maxsize = 0;
void DFS(int index, int height) {
++hashTable[height];
if (hashTable[height] > hashTable[maxsize]) maxsize = height;
for (int i = 0;i < child[index].size();++i) {
DFS(child[index][i], height + 1);
}
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 0;i < m;++i) {
int id, t;
scanf("%d %d", &id, &t);
for (int j = 0;j < t;++j) {
int c;
scanf("%d", &c);
child[id].push_back(c);
}
}
DFS(1, 1);
printf("%d %d\n", hashTable[maxsize], maxsize);
return 0;
}
PAT A1106 Lowest Price in Supply Chain
DFS
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
const int maxn = 100010;
vector<int> child[maxn];
int n, mindepth = maxn, cnt = 0;
double p, r;
void DFS(int index, int depth) {
if (depth == mindepth && child[index].size() == 0) ++cnt;
if (depth < mindepth && child[index].size() == 0) {
mindepth = depth;
cnt = 1;
}
for (int i = 0;i < child[index].size();++i) {
DFS(child[index][i], depth + 1);
}
}
int main() {
scanf("%d %lf %lf", &n, &p, &r);
r /= 100;
for (int i = 0;i < n;++i) {
int cnum;
scanf("%d", &cnum);
for (int j = 0;j < cnum;++j) {
int c;
scanf("%d", &c);
child[i].push_back(c);
}
}
DFS(0, 0);
printf("%.4f %d", p * pow((1 + r), mindepth), cnt);
return 0;
}
PAT A1004 Counting Leaves
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 110;
vector<int> child[maxn];
int n, m, hashTable[maxn] = { 0 }, maxheight;
void DFS(int index, int height) {
if (child[index].size() == 0) ++hashTable[height];
if (height > maxheight) maxheight = height;
for (int i = 0;i < child[index].size();++i) {
DFS(child[index][i], height + 1);
}
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 0;i < m;++i) {
int id, cnum;
scanf("%d %d", &id, &cnum);
for (int j = 0;j < cnum;++j) {
int c;
scanf("%d", &c);
child[id].push_back(c);
}
}
DFS(1, 0);
for (int i = 0;i <= maxheight;++i) {
if (i > 0) printf(" ");
printf("%d", hashTable[i]);
}
printf("\n");
return 0;
}
PAT A1053 Path of Equal Weight
这题有点难,要注意的点有
1、要用用path存下路径,方法1是申请path数组,通过递归获得的numNode作为下标,每递归下一层numNode+1;方法2是使用vector<int>path
这样递归的时候不需要numNode,当达到递归边界时直接使用path.size()
作为循环条件即可。
2、输出的条件为从大至小输出,因此需要在DFS前先将所有结点的child由大至小排列,这样递归出结果时,结果默认是由大至小。
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 110;
struct node {
int data;
vector<int> child;
}Node[maxn];
int n, m, s;
vector<int> path;
bool cmp(int a, int b) {
return Node[a].data > Node[b].data;
}
void DFS(int index, int sum) {
if (sum > s) return;
if (sum == s) {
if (Node[index].child.size() == 0) {
for (int i = 0;i < path.size();++i) {
if (i > 0) printf(" ");
printf("%d", Node[path[i]].data);
}
printf("\n");
return;
}
else return;
}
for (int i = 0;i < Node[index].child.size();++i) {
int child = Node[index].child[i];
path.push_back(child);
DFS(child, sum + Node[child].data);
path.pop_back();
}
}
int main() {
scanf("%d %d %d", &n, &m, &s);
for (int i = 0;i < n;++i) {
scanf("%d", &Node[i].data);
}
for (int i = 0;i < m;++i) {
int id, cnum;
scanf("%d %d", &id, &cnum);
for (int j = 0;j < cnum;++j) {
int child;
scanf("%d", &child);
Node[id].child.push_back(child);
}
sort(Node[id].child.begin(), Node[id].child.end(), cmp);
}
path.push_back(0);
DFS(0, Node[0].data);
return 0;
}
《算法笔记》9.4小节——数据结构专题(2)->二叉查找树(BST)
Codeup
二叉排序树
挺坑的,有相同元素也不讲,每个数据后面有空格
#include<cstdio>
#include<vector>
using namespace std;
struct node {
int data;
node* lchild, * rchild;
};
void insert(node*& root, int data) {
if (root == NULL) {
root = new node;
root->data = data;
root->lchild = root->rchild = NULL;
return;
}
if (data < root->data) insert(root->lchild, data);
else if (data > root->data) insert(root->rchild, data);//这里不能写else因为会有相同元素
}
void preOrder(node* root) {
if (root == NULL) return;
printf("%d ", root->data);
preOrder(root->lchild);
preOrder(root->rchild);
}
void inOrder(node* root) {
if (root == NULL) return;
inOrder(root->lchild);
printf("%d ", root->data);
inOrder(root->rchild);
}
void postOrder(node* root) {
if (root == NULL) return;
postOrder(root->lchild);
postOrder(root->rchild);
printf("%d ", root->data);
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
node* root = NULL;
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &temp);
insert(root, temp);
}
preOrder(root);
printf("\n");
inOrder(root);
printf("\n");
postOrder(root);
printf("\n");
}
return 0;
}
二叉搜索树
#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
struct node {
int data;
node* lchild, * rchild;
};
bool flag = true;
void insert(node*& root, int data) {
if (root == NULL) {
root = new node;
root->data = data;
root->lchild = root->rchild = 0;
return;
}
if (data < root->data) insert(root->lchild, data);
else if (data > root->data) insert(root->rchild, data);
}
void compare(node* root1, node* root2) {//比较函数
if (flag == false) return;//如果flag已经为false则直接退出
else {
if ((root1 == NULL && root2 != NULL) || (root2 == NULL && root1 != NULL)) {
flag = false;
return;
}
if (root1 != NULL && root2 != NULL) {
if (root1->data != root2->data) {
flag = false;
return;
}
else {
compare(root1->lchild, root2->lchild);
compare(root1->rchild, root2->rchild);
}
}
}
}
int main() {
int n;
while (scanf("%d", &n), n) {
string num;
node* root = NULL, com;
getchar();//吸收空格
getline(cin, num);
for (int i = 0;i < num.length();++i) {
insert(root, num[i] - '0');
}
for (int i = 0;i < n;++i) {
num.clear();
getline(cin, num);
node* comroot = NULL;
for (int j = 0;j < num.length();++j) {
insert(comroot, num[j] - '0');
}
flag = true;
compare(root, comroot);
if (flag == true) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
配套实战指南
PAT A1043 Is It a Binary Search Tree
不要试图去找什么规律,直接构造出树来遍历即可
#include<cstdio>
#include<vector>
using namespace std;
struct node{
int data;
node* lchild,*rchild;
};
int n;
vector<int> origin,pre,preM,post,postM;
void insert(node* &root,int data){
if(root==NULL){
root=new node;
root->data=data;
root->lchild=root->rchild=NULL;
return;
}
if(data<root->data) insert(root->lchild,data);
else insert(root->rchild, data);
}
void preOrder(node *root){
if(root==NULL) return;
pre.push_back(root->data);
preOrder(root->lchild);
preOrder(root->rchild);
}
void preOrderMirror(node *root){
if(root==NULL) return;
preM.push_back(root->data);
preOrderMirror(root->rchild);
preOrderMirror(root->lchild);
}
void postOrder(node *root){
if(root==NULL) return;
postOrder(root->lchild);
postOrder(root->rchild);
post.push_back(root->data);
}
void postOrderMirror(node *root){
if(root==NULL) return;
postOrderMirror(root->rchild);
postOrderMirror(root->lchild);
postM.push_back(root->data);
}
int main(){
scanf("%d",&n);
node *root=NULL;
for(int i=0;i<n;++i){
int key;
scanf("%d",&key);
insert(root,key);
origin.push_back(key);
}
preOrder(root);
preOrderMirror(root);
if(origin==pre){
postOrder(root);
printf("YES\n");
for(int i=0;i<n;++i){
if(i>0) printf(" ");
printf("%d",post[i]);
}
}else if(origin==preM){
postOrderMirror(root);
printf("YES\n");
for(int i=0;i<n;++i){
if(i>0) printf(" ");
printf("%d",postM[i]);
}
}else{
printf("NO");
}
printf("\n");
return 0;
}
PAT A1064 Complete Binary Search Tree
这道题的思路并不好想到,由于二叉查找树通过中序遍历得到的序列是递增序列,因此对静态二叉树中序遍历并将值不断填入,数组中保存的即是BST的层序遍历。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1010;
int n, cnt = 1;
int BST[maxn], CBT[maxn] = { 0 };
void inOrder(int i) {//中序遍历
if (i > n) return;
inOrder(2 * i);
CBT[i] = BST[cnt++];
inOrder(2 * i + 1);
}
int main() {
scanf("%d", &n);
for (int i = 1;i <= n;++i) {
scanf("%d", &BST[i]);
}
sort(BST + 1, BST + n + 1);
inOrder(1);
for (int i = 1;i <= n;++i) {
if (i > 1) printf(" ");
printf("%d", CBT[i]);
}
return 0;
}
PAT A1099 Build A Binary Search Tree
将num序列递增排序,即为BST的中序遍历,然后通过中序遍历将数字填入BST中,最后层序遍历输出BST;
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 110;
struct node {
int data;
int lchild, rchild;
}Node[maxn];
int cnt = 0, n;
vector<int> num;
void inOrder(int index) {//中序遍历
if (index == -1) return;
inOrder(Node[index].lchild);
Node[index].data = num[cnt++];
inOrder(Node[index].rchild);
}
void BFS() {//层序遍历
queue<int> qu;
qu.push(0);
while (!qu.empty()) {
int top = qu.front();
qu.pop();
if (cnt > 0) printf(" ");
++cnt;
printf("%d", Node[top].data);
if (Node[top].lchild != -1) qu.push(Node[top].lchild);
if (Node[top].rchild != -1) qu.push(Node[top].rchild);
}
}
int main() {
scanf("%d", &n);
for (int i = 0;i < n;++i) scanf("%d %d", &Node[i].lchild, &Node[i].rchild);
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &temp);
num.push_back(temp);
}
sort(num.begin(), num.end());//排序后即为中序遍历
inOrder(0);
cnt = 0;
BFS();
return 0;
}
《算法笔记》9.5小节——数据结构专题(2)->平衡二叉树(AVL)
Codeup
算法9-9~9-12:平衡二叉树的基本操作
#include<cstdio>
#include<algorithm>
using namespace std;
struct node {
int data, height;
node* lchild, * rchild;
};
int n, k;
int getHeight(node* root) {
if (root == NULL) return 0;
return root->height;
}
int getBalanceFactor(node* root) {
return getHeight(root->lchild) - getHeight(root->rchild);
}
void updateHeight(node* root) {
root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
}
void L_rotate(node*& root) {
node* temp = root->rchild;
root->rchild = temp->lchild;
temp->lchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
void R_rotate(node*& root) {
node* temp = root->lchild;
root->lchild = temp->rchild;
temp->rchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
void insert(node*& root, int data) {
if (root == NULL) {
root = new node;
root->data = data;
root->lchild = root->rchild = NULL;
root->height = 1;
return;
}
if (data < root->data) {
insert(root->lchild, data);
updateHeight(root);
if (getBalanceFactor(root) == 2) {
if (getBalanceFactor(root->lchild) == 1) {
R_rotate(root);
}
else if (getBalanceFactor(root->lchild) == -1) {
L_rotate(root->lchild);
R_rotate(root);
}
}
}
else {
insert(root->rchild, data);
updateHeight(root);
if (getBalanceFactor(root) == -2) {
if (getBalanceFactor(root->lchild) == -1) {
L_rotate(root);
}
else if (getBalanceFactor(root->lchild) == 11) {
R_rotate(root->lchild);
L_rotate(root);
}
}
}
}
void search(node* root, int x) {
if (root == NULL) {
printf("0 ");
return;
}
if (x == root->data) {
printf("1 ");
return;
}
else if (x < root->data) search(root->lchild, x);
else search(root->rchild, x);
}
int main() {
while (scanf("%d %d", &n, &k) != EOF) {
node* root;
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &temp);
insert(root, temp);
}
for (int i = 0;i < k;++i) {
int s;
scanf("%d", &s);
search(root, s);
}
}
return 0;
}
配套实战指南
PAT A1066 Root of AVL Tree
代码很长,但其实没有特别难
最开始提交全部段错误,对比了一下参考书上发现写的没问题,在本地运行也没问题,最后把node* root放在外面定义了,就能AC了,原因有些不明
#include<cstdio>
#include<algorithm>
using namespace std;
struct node {
int data, height;
node* lchild, * rchild;
}*root;
int getHeight(node* root) {
if (root == NULL) return 0;
return root->height;
}
int getBalanceFactor(node* root) {
return getHeight(root->lchild) - getHeight(root->rchild);
}
void updateHeight(node* root) {
root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
}
void L_rotate(node*& root) {//用引用
node* temp = root->rchild;
root->rchild = temp->lchild;
temp->lchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
void R_rotate(node*& root) {
node* temp = root->lchild;
root->lchild = temp->rchild;
temp->rchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
void insert(node*& root, int data) {
if (root == NULL) {
root = new node;
root->data = data;
root->lchild = root->rchild = NULL;
root->height = 1;
return;
}
if (data < root->data) {
insert(root->lchild, data);
updateHeight(root);
if (getBalanceFactor(root) == 2) {
if (getBalanceFactor(root->lchild) == 1) {
R_rotate(root);
}
else if (getBalanceFactor(root->lchild) == -1) {
L_rotate(root->lchild);
R_rotate(root);
}
}
}
else {
insert(root->rchild, data);
updateHeight(root);
if (getBalanceFactor(root) == -2) {
if (getBalanceFactor(root->rchild) == -1) {
L_rotate(root);
}
else if (getBalanceFactor(root->rchild) == 1) {
R_rotate(root->rchild);
L_rotate(root);
}
}
}
}
int main() {
int n;
scanf("%d", &n);
//node* root;
for (int i = 0;i < n;++i) {
int data;
scanf("%d", &data);
insert(root, data);
}
printf("%d", root->data);
return 0;
}
《算法笔记》9.6小节——数据结构专题(2)->并查集
Codeup
通信系统
每个端点不会重复收到信息。因此并查集中只能有一个根结点,而且不能有环。判断不能有环可以用结点数-1大于等于边数,其实是连通图而且不会形成环的时候结点数-1=边数。
#include<cstdio>
const int maxn = 1010;
int father[maxn];
bool isRoot[maxn] = { false };
void init(int n) {
for (int i = 1;i <= n;++i) {
father[i] = i;
isRoot[i] = false;
}
}
int findFather(int x) {
int a = x;
while (x != father[x]) {
x = father[x];
}
while (a != father[a]) {
int z = a;
a = father[a];
father[z] = x;
}
return x;
}
void Union(int a, int b) {
int faA = findFather(a);
int faB = findFather(b);
if (faA != faB) {
father[faA] = faB;
}
}
int main() {
int n, m, a, b;
while (scanf("%d %d", &n, &m), m || n) {
init(n);
for (int i = 0;i < m;++i) {
scanf("%d %d", &a, &b);
Union(a, b);
}
for (int i = 1;i <= n;++i) {
isRoot[findFather(i)] = true;
}
int ans = 0;
for (int i = 1;i <= n;++i) {
ans += isRoot[i];
}
if (ans == 1 && m == n - 1) printf("Yes\n");
else printf("No\n");
}
return 0;
}
畅通工程
#include<cstdio>
const int maxn = 1010;
int father[maxn];
int isRoot[maxn] = { 0 };
void init(int n) {
for (int i = 1;i <= n;++i) {
father[i] = i;
isRoot[i] = 0;
}
}
int findFather(int x) {
int a = x;
while (x != father[x]) {
x = father[x];
}
while (a != father[a]) {
int z = a;
a = father[a];
father[z] = x;
}
return x;
}
void Union(int a, int b) {
int faA = findFather(a);
int faB = findFather(b);
if (faA != faB) {
father[faA] = faB;
}
}
int main() {
int m, n, a, b;
while (scanf("%d", &n), n) {
scanf("%d", &m);
init(n);
for (int i = 0;i < m;++i) {
scanf("%d %d", &a, &b);
Union(a, b);
}
for (int i = 1;i <= n;++i) {
++isRoot[findFather(i)];
}
int cnt = 0;
for (int i = 1;i <= n;++i) {
if (isRoot[i] > 0) ++cnt;
}
printf("%d\n", cnt - 1);
}
return 0;
}
How Many Tables
#include<cstdio>
const int maxn = 1010;
int father[maxn];
bool isRoot[maxn] = { false };
void init(int n) {
for (int i = 1;i <= n;++i) {
father[i] = i;
isRoot[i] = false;
}
}
int findFather(int x) {
int a = x;
while (x != father[x]) {
x = father[x];
}
while (a != father[a]) {
int z = a;
a = father[a];
father[z] = x;
}
return x;
}
void Union(int a, int b) {
int faA = findFather(a);
int faB = findFather(b);
if (faA != faB) {
father[faA] = faB;
}
}
int main() {
int t;
scanf("%d", &t);
for (int i = 0;i < t;++i) {
int n, m, a, b;
scanf("%d %d", &n, &m);
init(n);
for (int j = 0;j < m;++j) {
scanf("%d %d", &a, &b);
Union(a, b);
}
for (int j = 1;j <= n;++j) {
isRoot[findFather(j)] = true;
}
int cnt = 0;
for (int j = 1;j <= n;++j) {
if (isRoot[j] == true) ++cnt;
}
printf("%d\n", cnt);
}
return 0;
}
More is better
题目不难但写了很久,粗心死
#include<cstdio>
const int maxn = 10000010;
int friends[maxn];
int isRoot[maxn] = { 0 };
void init() {
for (int i = 1;i < maxn;++i) {
friends[i] = i;
isRoot[i] = 0;
}
}
int findFriends(int x) {
int a = x;
while (x != friends[x]) x = friends[x];
while (a != friends[a]) {
int z = a;
a = friends[a];
friends[z] = x;
}
return x;
}
void Union(int a, int b) {
int frA = findFriends(a);
int frB = findFriends(b);
if (frA != frB) {
friends[frA] = frB;
}
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
init();
for (int i = 0;i < n;++i) {
int a, b;
scanf("%d %d", &a, &b);
Union(a, b);
}
int max = 0;
for (int i = 1;i < maxn;++i) {
++isRoot[findFriends(i)];
if (isRoot[friends[i]] > max) max = isRoot[friends[i]];
}
printf("%d\n", max);
}
return 0;
}
配套实战指南
1107 Social Clusters
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1010;
int father[maxn];
int isRoot[maxn]={0};
int course[maxn]={0};
void init(int n){
for(int i=1;i<=n;++i){
father[i]=i;
isRoot[i]={0};
}
}
int findFather(int x){
int a=x;
while(x!=father[x]){
x=father[x];
}
while(a!=father[a]){
int z=a;
a=father[a];
father[z]=x;
}
return x;
}
void Union(int a,int b){
int farA=findFather(a);
int farB=findFather(b);
if(farA!=farB){
father[farA]=farB;
}
}
bool cmp(int a,int b){
return a>b;
}
int main(){
int n;
scanf("%d",&n);
init(n);//别忘了初始化
for(int i=1;i<=n;++i){
int m;
scanf("%d:",&m);
for(int j=0;j<m;++j){
int k;
scanf("%d",&k);
if(course[k]==0){
course[k]=i;
}else{
Union(i,findFather(course[k]));//注意这里要写findFather(course[k])
}
}
}
for(int i=1;i<=n;++i){
++isRoot[findFather(i)];
}
int ans=0;
for(int i=1;i<=n;++i){
if(isRoot[i]>0) ++ans;
}
printf("%d\n",ans);
sort(isRoot+1,isRoot+n+1,cmp);
for(int i=1;i<=ans;++i){
if(i>1) printf(" ");
printf("%d",isRoot[i]);
}
return 0;
}
《算法笔记》9.7小节——数据结构专题(2)->堆
Codeup
算法10-10,10-11:堆排序
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100010;
int heap[maxn];
int n;
void downAdjust(int low, int high) {
int i = low, j = 2 * i;
while (j <= high) {//j<=high 不是j<=n
if (j + 1 <= high && heap[j + 1] > heap[j]) {
j = j + 1;
}
if (heap[j] > heap[i]) {
swap(heap[j], heap[i]);
i = j;
j = i * 2;
}
else {
break;
}
}
}
void createHeap() {
for (int i = n / 2;i >= 1;--i) {
downAdjust(i, n);
}
}
void heapSort() {
createHeap();
for (int i = n;i > 1;--i) {
swap(heap[i], heap[1]);
downAdjust(1, i - 1);
}
}
int main() {
while (scanf("%d", &n) != EOF) {
for (int i = 1;i <= n;++i) {
scanf("%d", &heap[i]);
}
heapSort();
for (int i = 1;i <= n;++i) printf("%d ", heap[i]);
printf("\n");
}
return 0;
}
序列合并
题目给的数据量相当大,最开始想直接堆排序硬解,然后就收获了一堆的运行错误,然后尝试vector,一样运行错误,网上搜到的代码思路
#include<cstdio>
const int maxn = 100010;
int heap[maxn];
int a[maxn], b[maxn];
int n;
void downAdjust(int low, int high) {
int i = low, j = 2 * i;
while (j <= high) {
if (j + 1 <= high && heap[j + 1] > heap[j]) j = j + 1;
if (heap[j] > heap[i]) {
swap(heap[i], heap[j]);
i = j;
j = 2 * i;
}
else {
break;
}
}
}
void createHeap() {
for (int i = n / 2;i >= 1;--i) {
downAdjust(i, n);
}
}
void heapSort() {
for (int i = n;i > 1;--i) {
swap(heap[1], heap[i]);
downAdjust(1, i - 1);
}
}
int main() {
while (scanf("%d", &n) != EOF) {
for (int i = 1;i <= n;++i) {
scanf("%d", &a[i]);
}
for (int i = 1;i <= n;++i) {
scanf("%d", &b[i]);
heap[i] = a[1] + b[i];//先将a[1]与b中各元素的加和创建堆
}
createHeap();
for (int i = 2;i <= n;++i) {//对其他结果遍历
for (int j = 1;j <= n;++j) {
int x = a[i] + b[j];
if (x < heap[1]) {//heap[1]为大堆顶中最大的元素
heap[1] = x;
downAdjust(1, n);//插入x
}
else break;//如果大于最大元素则无需入堆
}
}
heapSort();
for (int i = 1;i <= n;++i) {
if (i > 1) printf(" ");
printf("%d", heap[i]);
}
printf("\n");
}
return 0;
}
合并果子(堆)
小顶堆堆实现
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 30010;
int n;
int heap[maxn];
void downAdjust(int low, int high) {//向下调整
int i = low, j = 2 * i;
while (j <= high) {
if (j + 1 <= high && heap[j + 1] < heap[j]) {
j = j + 1;
}
if (heap[j] < heap[i]) {
swap(heap[i], heap[j]);
i = j;
j = 2 * i;
}
else {
break;
}
}
}
void upAdjust(int low, int high) {//向上调整
int i = high, j = i / 2;
while (j >= low) {
if (heap[j] > heap[i]) {
swap(heap[j], heap[i]);
i = j;
j = i / 2;
}
else break;
}
}
void createHeap() {//创建堆
for (int i = n / 2;i >= 1;--i) {
downAdjust(i, n);
}
}
int deleteTop() {//删除堆顶元素并返回元素值
int temp = heap[1];
heap[1] = heap[n--];
downAdjust(1, n);
return temp;
}
void insert(int x) {//插入新元素
heap[++n] = x;
upAdjust(1, n);
}
int main() {
int ans = 0;
scanf("%d", &n);
for (int i = 1;i <= n;++i) {
scanf("%d", &heap[i]);
}
createHeap();
while (n > 1) {
int a = deleteTop();
int b = deleteTop();//得到小堆顶的两个最小元素
insert(a + b);//将其相加并将两元素和插入堆中
ans += a + b;
}
printf("%d", ans);
return 0;
}
优先队列实现
#include<cstdio>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int>> q;
int main() {
int n;
int temp, x, y, ans = 0;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%d", &temp);
q.push(temp);
}
while (q.size() > 1) {
x = q.top();
q.pop();
y = q.top();
q.pop();
q.push(x + y);
ans += x + y;
}
printf("%d\n", ans);
return 0;
}
配套实战指南
PAT A1098 Insertion or Heap Sort
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 110;
vector<int> origin, tempOri, changed;
int n;
bool insertSort() {
bool flag = false;
for (int i = 2;i < n;++i) {
if (i != 2 && tempOri == changed) {
flag = true;
}
int j = i, temp = tempOri[i];
while (tempOri[j - 1] > temp && j > 1) {
tempOri[j] = tempOri[j - 1];
--j;
}
tempOri[j] = temp;
if (flag) return true;
}
return false;
}
void downAdjust(int low, int high) {
int i = low, j = 2 * i;
while (j <= high) {
if (j + 1 <= high && tempOri[j + 1] > tempOri[j]) j = j + 1;
if (tempOri[j] > tempOri[i]) {
swap(tempOri[j], tempOri[i]);
i = j;
j = 2 * i;
}
else {
break;
}
}
}
void createHeap() {
for (int i = n / 2;i >= 1;--i) {
downAdjust(i, n);
}
}
void heapSort() {
createHeap();
bool flag = false;
for (int i = n;i > 1;--i) {
if (tempOri == changed) flag = true;
swap(tempOri[1], tempOri[i]);
downAdjust(1, i - 1);
if (flag == true) {
return;
}
}
}
int main() {
int temp;
origin.push_back(0);
tempOri.push_back(0);
changed.push_back(0);
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%d", &temp);
origin.push_back(temp);
}
tempOri = origin;
for (int i = 0;i < n;++i) {
scanf("%d", &temp);
changed.push_back(temp);
}
if (insertSort()) {
printf("Insertion Sort\n");
for (int i = 1;i <= n;++i) {
if (i > 1) printf(" ");
printf("%d", tempOri[i]);
}
}
else {
tempOri = origin;
heapSort();
printf("Heap Sort\n");
for (int i = 1;i <= n;++i) {
if (i > 1) printf(" ");
printf("%d", tempOri[i]);
}
}
return 0;
}
100000617 - 《算法笔记》9.8小节——图算法专题->哈夫曼树
算法6-12:自底向上的赫夫曼编码
算法6-13:自顶向下的赫夫曼编码
哈夫曼树
#include<cstdio>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int>> q;
int main() {
int n;
while (scanf("%d", &n) != EOF) {
int temp, x, y, ans = 0;
for (int i = 0;i < n;++i) {
scanf("%d", &temp);
q.push(temp);
}
while (q.size() > 1) {
x = q.top();
q.pop();
y = q.top();
q.pop();
q.push(x + y);
ans += x + y;
}
printf("%d\n", ans);
q.pop();
}
return 0;
}
Haffman编码
合并果子
同上一节