DS博客做業05--樹

1.本週學習總結

1.1思惟導圖

1.2談談你對樹結構的認識及學習體會

尚未理解樹以前感受樹很神祕(看過數據結構視頻),樹這種結構看上去很難以想象,究竟是怎麼實現而且操做的,學完二叉樹就感受這操做有點簡單。巧妙經過遞歸就把對樹杈的處理變成了對根和左右孩子的處理。
樹能夠處理大量的數據,可是對數的操做代碼量很少,由於大部分操做使用了遞歸,須要對遞歸有較好的理解,不然代碼很容易出現錯誤,並且很難發現。
樹這個數據結構很是實用,因此必需要掌握,好比目錄,排序等都須要樹,acm也會出現樹的題目。

2.PTA實驗做業

2.1.題目1:6-4 jmu-ds-表達式樹

2.1.1設計思路

建表達式樹使用兩個棧分別放樹和運算符,遍歷放表達式的字符串,遇到數字就建一個節點入棧,若是是運算符就要判斷是否優先級,若是比棧頂小,棧頂就能夠拿出來,用該運算符建一個節點,左右孩子爲樹棧最上面的兩個節點。計算表達式,經過樹的後續遍歷就能夠。
void InitExpTree(BTree &T, string str)
{
    聲明兩個棧,一個樹棧,一個運算符棧 
    Chsta.push('#')運算符棧入棧一個#號避免爲空 

    for (遍歷字符串str)
    {
        if (若是是數字)
        {
            建節點 
            Bt->data = str[i]
            左右孩子置爲空 
            Bt->lchild = Bt->rchild = NULL
            入樹棧 
            BTsta.push(Bt)
        }
        else  若是是運算符 
        {
            調用Precede函數比較優先級 
            char result = Precede(Chsta.top(), str[i]);
            if (若是比運算符棧棧頂大)
            {
                入棧 
                Chsta.push(str[i]);
            }
            else if (若是相等)說明是括號 
            {
                出棧 
                Chsta.pop();
            }
            else 若是比運算符棧棧頂小 
            {
                用運算符建一個節點 
                Bt->data = Chsta.top();
                Chsta.pop();
                左右孩子爲樹棧頂的兩個 
                Bt->rchild = BTsta.top();
                BTsta.pop();
                Bt->lchild = BTsta.top();
                BTsta.pop();
                最後入棧 
                BTsta.push(Bt);
            }

        }
    }
    while (運算符棧還有運算符)
    {
        用運算符建一個節點 
        Bt->data = Chsta.top();
        Chsta.pop();
        左右孩子爲樹棧頂的兩個 
        Bt->rchild = BTsta.top();
        BTsta.pop();
        Bt->lchild = BTsta.top();
        BTsta.pop();
        最後入棧 
        BTsta.push(Bt);
    }
}

double EvaluateExTree(BTree T)
{
    double left, right放左孩子和右孩子 
    if (T == NULL)
    {
        return 0;
    }
    if (若是是葉子節點) 
    {
        return T->data-'0' 返回節點值 
    }
    遞歸左孩子 
    left = EvaluateExTree(T->lchild);
    遞歸右孩子 
    right = EvaluateExTree(T->rchild);
    計算 
    switch (T->data) // 根據b結點作相應運算
    {
    case '+':
        return left + right;
    case '-':
        return left - right;
    case '*':
        return left * right;
    case '/':
        if (right != 0)
            return left / right;
        else
        {
            cout<<"divide 0 error!"; // 除0異常退出
            exit(0);
        }
            
    }
}

2.1.2代碼截圖



2.1.3本題PTA提交列表說明


Q:沒有考慮括號兩個括號相遇時要出棧ios

2.2.題目2:7-7 朋友圈

2.2.1設計思路

該題是應用並查集,每一個俱樂部的成員和該俱樂部第一個成員合併,最後哈希獲得最大的朋友圈人數,爲了減小查找時間,盡力讓節點指向根。
#include <iostream>
using namespace std;
int stu[30010]定義全局變量 
int Find(int x)
{
    if (若是x等於stu[x])說明根是本身 
    {
        返回 stu[x];
    }
    else 繼續遞歸找根 
    {
        
        return stu[x]=Find(stu[x]);儘可能讓節點指向根 
    }
}
void add(int a, int b)將a和b合併 
{
    int x = Find(a);查找根 
    int y = Find(b);查找根 
    if (x != y)合併 
    {
        stu[x] = y;
    }
}
int main()
{
    int N, M;
    cin >> N >> M;
    for (int i = 1; i <= N; i++) 並查集初始化,根是本身 
    {
        stu[i] = i;
    }
    for (int i = 0; i < M; i++)
    {
        int count,a;
        cin >> count >> a;
        int b;
        for (int j = 0; j < count - 1; j++)
        {
            cin >> b;
            add(a, b);//調用合併函數 
        }
    }
    int max = 0;
    int myhash[30010] = { 0 };hash求最大朋友圈人數 
    for (int i = 1; i <= N; i++)
    {
        int temp = Find(i);找根
        myhash[temp]++;根同樣加一
        if (myhash[temp] > max)找最大值     
                {
            max = myhash[temp];
        }
    }
    cout << max;
    return 0;
}

2.2.2代碼截圖


2.2.3本題PTA提交列表說明


Q:在遞歸時儘可能讓節點都指向根數據結構

2.3.題目3:7-6 修理牧場

2.3.1設計思路

這個就是一個哈夫曼樹,使用multiset(set不能存放多個相同數據),multiset是從小到大排序好的,每次取最小兩個數據相加,而後做爲新的元素加入multiset中(固然這兩個得刪除),直到只剩一個數據,用sum記錄全部相加和,sum即爲所求最小花費。
  • 注意使用erase刪除元素時要用指針,若是直接使用數據會把multiset中全部該數據刪除,好比erase(3),將會刪除全部的3

2.3.2代碼截圖

2.3.3本題PTA提交列表說明

A:此題難點不是在於代碼,而是思路,當時恰好學完哈夫曼樹,而後又有STL的加持,就會顯得很輕鬆就過。ide

3.閱讀代碼

3.1 題目

題目描述函數

在桌面上有一排硬幣,共NN枚,每一枚硬幣均爲正面朝上。如今要把全部的硬幣翻轉成反面朝上,規則是每次可翻轉任意N-1N−1枚硬幣(正面向上的被翻轉爲反面向上,反之亦然)。求一個最短的操做序列(將每次翻轉N-1枚硬幣成爲一次操做)。學習

輸入輸出格式lua

輸入格式:
一個天然數NN(NN爲不大於100100的偶數)。spa

輸出格式:
第一行包含一個整數SS,表示最少須要的操做次數。接下來的SS行每行分別表示每次操做後桌上硬幣的狀態(一行包含NN個整數(00或11),表示每一個硬幣的狀態:00――正面向上,和11――反面向上,不容許出現多餘空格)。設計

對於有多種操做方案的狀況,則只需字典序最小輸出一種。指針

輸入輸出樣例code

輸入樣例#1: 複製
4
輸出樣例#1: 複製
4
0111
1100
0001
1111

3.2 解題思路

翻n-1枚硬幣,就是有一枚不翻,也能夠理解爲翻一枚

3.3 代碼截圖

3.4 學習體會

邏輯性的題目通常能夠找出規律性,看上去可能很麻煩可是能夠其實代碼量不多,或者有時候能夠巧妙地藉助STL完成解題。
相關文章
相關標籤/搜索