算法笔记Codeup、pat刷题记录(含个人笔记)第九章

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编码

合并果子

同上一节

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值