title: ACM-数据结构
date: 2015-01-30 10:36:05
categories:
- 白皮书
tags:
{% blockquote 本文出自 http://svtter.com svtter.com %}
本文可以随意转载,但是转载请保留本信息.
{% endblockquote %}
Uvaoj的判题效率不是很高。。所以直接开下一章节。题目慢慢刷,先过一遍书,不然书都看不完了TAT。。
6.1 栈和队列
卡片游戏,回顾了下队列和STL
c
#include <stdio.h> #include <queue> #include <iostream> using namespace std; const int maxn = 100; int q[maxn]; void ace() { void ace2(int); int n; scanf("%d", &n); //init for(int i = 0; i < n; i++) q[i] = i+1; int front , rear; front = 0, rear = n; // 队列不为空 while(front != rear) { printf("%d ", q[front++]); q[rear++] = q[front++]; } printf("\n"); ace2(n); } // STL void ace2(int n) { queue <int> q; for(int i = 1; i <= n; i++) q.push(i); while(!q.empty()) { printf("%d ", q.front()); q.pop(); q.push(q.front()); q.pop(); } printf("\n"); } int main(int argc, const char *argv[]) { ace(); return 0; }
6.1.2栈的STL
#include <stdio.h>
#include <iostream>
#include <stack>
using namespace std;
const int maxn = 200;
int s[maxn];
void ace()
{
int n;
int a[maxn];
int temp, top;
int p, set;
while(~scanf("%d", &n))
{
top = -1, p = 0, set = 1;
for(int i = 0; i < n; i++) a[i] = i+1;
for(int i = 0; i < n; i++)
{
scanf("%d", &temp);
// 如果无法完成序列,只吸收输入值
if(!set) continue;
if(temp == a[p]) p++;
else if(top != -1 && temp == s[top]) top--;
else while(temp != a[p])
{
s[++top] = a[p];
p++;
if(p == n)
{
set = 0;
break;
}
}
}
if(set) printf("Yes");
else printf("No");
printf("\n");
}
}
void ace2()
{
int n;
int a[maxn];
int temp, p, set;
while(~scanf("%d", &n))
{
stack <int> s;
p = 0, set = 1;
for(int i = 0; i < n; i++) a[i] = i+1;
for(int i = 0; i < n; i++)
{
scanf("%d", &temp);
// 如果无法完成序列,只吸收输入值
if(!set) continue;
if(temp == a[p]) p++;
else if(!s.empty() && temp == s.top()) s.pop();
else while(temp != a[p])
{
s.push(a[p]);
p++;
if(p == n)
{
set = 0;
break;
}
}
}
if(set) printf("Yes");
else printf("No");
printf("\n");
}
}
int main()
{
ace2();
return 0;
}
6.2 链表和随机数发生器
链表的相关部分就不在赘述了。主要是随机数发生器。
很多人喜欢用rand()%N
得到一个随即整数,但是n大于RAND_MAX
的时候,就不好用了。
于是使用(double)rand()/RAND_MAX
,然后在扩大n-1
倍以后四舍五入,再+1
例如这样:
c
// 获取1~m的随即整数 int random(int m) { double a = (double)rand() / RAND_MAX; return (int) (a * (m-1) + 0.5); }
6.3 二叉树
-
root == 1
则左root*2
右root*2+1
-
root == 0
则左root*2+1
右root*2+2
6.3.1 小球下落
c
#include <stdio.h> #include <stdlib.h> #include <string.h> using namespace std; const int maxn = 1000000; int tree[maxn]; int main() { int d, b; while(~scanf("%d %d", &d, &b)) { memset(tree, 0, sizeof(tree)); int p; int td; while(b--) { p = 1; td = d-1; while(td--) { if(tree[p] == 0) { tree[p] = 1; p = p * 2; } else { tree[p] = 0; p = p * 2 + 1; } } if(b == 0) printf("%d\n", p); } } return 0; }
书上的做法1.经过计算/
c
#include <stdio.h> #include <stdlib.h> #include <string.h> using namespace std; const int maxd = 20; int s[1 << maxd]; // 最大结点个数为2^maxd -1 int main() { int D, I; while(scanf("%d %d", &D, &I) == 2) { memset(s, 0, sizeof(s)); int k, n = (1<<D)-1; for(int i = 0; i < n; i++) { k = 1; for(;;) { // 01变换 s[k] = !s[k]; k = s[k] ? k*2 : k*2+1; if(k > n) break; } } printf("%d\n", k/2); } return 0; }
6.3.2 层次遍历
如果不使用指针,存在两种方式。
- 使用一个单独的Node数组,然后让子结点分别指回这个数组
Node * newnode()() { Node * u = &node[++cnt]; u->left = u->right=NULL; return u}
- 使用两个数组
const int root = 1;
void newtree() { left[root] = right[root] = 0; cnt = root;}
void newnode() { int u = ++cnt; left[u] = right[u] = 0; return u;}
- 第一种方式快一点。
c
#include <stdio.h> #include <string.h> #include <malloc.h> #include <assert.h> #include <queue> using namespace std; const int maxn = 2000; struct Node { int have_value; int v; Node *left, *right; }; Node * newnode() { Node *u = (Node *) malloc(sizeof(Node)); if (u != NULL) { u->have_value = 0; u->left = u->right = NULL; } return u; } Node *root; int failed; void addnode(int v, char *s) { int len = strlen(s); Node *u = root; for(int i = 0; i < len; i++) { if(s[i] == 'L') { if(u->left == NULL) u->left = newnode(); u = u->left; } else if(s[i] == 'R') { if(u->right == NULL) u->right = newnode(); u = u->right; } } if(u->have_value) failed = 1; u->v = v; u->have_value = 1; } int input() { char s[maxn]; while(1) { if(scanf("%s", s) != 1) return 0; if(!strcmp("()", s)) break; int v; sscanf(&s[1], "%d", &v); addnode(v, strchr(s, ',')+1); } return 1; } int ans[maxn], n; int bfs() { int front, rear; Node *q[maxn]; front = 0, rear = 1; q[0] = root; n = 0; while(front != rear) { Node *u = q[front]; if(!u->have_value) return 0; front++; ans[n++] = u->v; if(u->left != NULL) q[rear++] = u->left; if(u->right != NULL) q[rear++] = u->right; } return 1; } void remove_tree(Node *u) { if(u == NULL) return ; remove_tree(u->left); remove_tree(u->right); free(u); } int main() { freopen("input", "r", stdin); root = newnode(); while(input()) { if(failed || !bfs()) printf("-1"); else for(int i = 0; i < n; i++) printf("%d ", ans[i]); printf("\n"); remove_tree(root); root = newnode(); } return 0; }
6.3.3 二叉树重建
不同的遍历输出。
c
#include <stdio.h> #include <string.h> #include <malloc.h> using namespace std; const int maxn = 2000; char s1[maxn]; char s2[maxn]; char ans[maxn]; void build(int n, char *s1, char *s2, char *s) { if(n <= 0) return; int p = strchr(s2, s1[0]) - s2; build(n, s1, s2, s); build(n-p-1, s1+p+1, s2+p+1, s+p); s[n-1] = s1[0]; } int main() { freopen("input", "r", stdin); while(~scanf("%s %s", s1, s2)) { int n = strlen(s1); build(n, s1, s2, ans); ans[n] = '\0'; printf("%s\n", ans); } return 0; }
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。