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*2root*2+1
  • root == 0则左root*2+1root*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;
}

svtter
209 声望37 粉丝

更喜欢原型开发


引用和评论

0 条评论