zoukankan      html  css  js  c++  java
  • DS博客作业03--树

    0.PTA得分截图

    1.本周学习总结

    1.1 总结树及串内容

    思维导图

    • ·串的BFKMP算法
    //BF算法(强行暴力匹配)
    #include <iostream>
    #include <string>
    using namespace std;
    int BF(string s, string p)
    {
        int i = 0, j = 0;
        while (i < s.length() && j < p.length())  //j一旦超过模式长度,代表匹配成功,跳出循环
        {
            if (s[i] == p[j])               //如果当前位置匹配,则后移一位匹配下一位置
            {
                i++;
                j++;
            }
            else                        //当前位置不匹配则回溯
            {
                i = i - j + 1;
                j = 0;
            }  
    
    
        }
        if (j >= p.length())
        {
            return i - p.length();  //返回匹配成功的位置
        }
        else
            return 0;
    }
    
    int main()
    {
        string s, p;
        cin >> s >> p;
        cout << "BF算法匹配结果为:" << BF(s, p) << endl;
        return 0;
    }
    
    KMP算法
    #include <iostream>
    #include <string>
    using namespace std;
    
    void Getnext(int next[], string t)
    {
        int j = 0, k = -1;
        next[0] = -1;
        while (j < t.size())
        {
            if (k == -1 || t[j] == t[k])
            {
                j++; 
                k++;
                next[j] = k;
            }
            else
            {
                k = next[k];
            }
        }
    }
    int KMP(string s, string p)
    {
        int next[100], i = 0, j = 0;
        Getnext(next,p);
        while (i <= s.size() && j <= p.size())
        {
            if (j == -1 || s[i] == p[j])
            {
                i++;
                j++;
            }
            else
            {
                j = next[j];
            }
        }
        if (j >= p.size())
        {
            return (i - p.size());
        }
        else
        {
            return (-1);
        }
    }
    
    
    int main()
    {
        string s, p;
        cin >> s >> p;
        cout << "BF算法匹配结果为:" << KMP(s, p) << endl;
        return 0;
    }
    
    • ·二叉树存储结构、建法、遍历及应用
    //存储结构
    typedef struct node 
    {
    	int data;
    	struct node* lchild, * rchild;
    
    }BTnode;
    typedef BTnode* BTree;
    
    //前序创建二叉树
    BTree CreateTree(string str, int &i)
    {
    	BTree bt;
    	int len = str.size();
    	if (i > len - 1 || str[i] == '#')return NULL;
    	bt = new BTnode;
    	bt->data = str[i];
    	bt->lchild = CreateTree(str, ++i);
    	bt->rchild = CreateTree(str, ++i);
    	return bt;
    }
    
    //遍历输出二叉树
    //前序
    void PreorderPrintLeaves(BinTree BT)
    {
        if (BT)
        {
            cout<<BT->data;
            PreorderPrintLeaves(BT->Left);
            PreorderPrintLeaves(BT->Right);
        }
    }
    //中序
    void PreorderPrintLeaves(BinTree BT)
    {
        if (BT)
        {
            PreorderPrintLeaves(BT->Left);
            cout<<BT->data;
            PreorderPrintLeaves(BT->Right);
        }
    }
    //后序
    void PreorderPrintLeaves(BinTree BT)
    {
        if (BT)
        {
            PreorderPrintLeaves(BT->Left);
            PreorderPrintLeaves(BT->Right);
            cout<<BT->data;
        }
    }
    

    应用:

    代码实现

    #include<iostream>
    #include<string>
    using namespace std;
    
    typedef struct node 
    {
    	int data;
    	struct node* lchild, * rchild;
    
    }BTnode;
    typedef BTnode* BTree;
    
    BTree CreateTree(string str, int&i);
    void InorderPrintTree(BTree bt);
    
    int main()
    {
    	string str;
    	str.resize(101);
    	while (scanf("%s", &str[0]) != EOF)
    	{
    		BTree BT;
    		int i = 0;
    		BT = CreateTree(str, i);
    		InorderPrintTree(BT);
    		cout << endl;
    	}
    }
    
    BTree CreateTree(string str, int &i)
    {
    	BTree bt;
    	int len = str.size();
    	if (i > len - 1 || str[i] == '#')return NULL;
    	bt = new BTnode;
    	bt->data = str[i];
    	bt->lchild = CreateTree(str, ++i);
    	bt->rchild = CreateTree(str, ++i);
    	return bt;
    }
    
    void InorderPrintTree(BTree bt)
    {
    	if (!bt) return ;
    	else
    	{
    		InorderPrintTree(bt->lchild);
    		printf("%c ", bt->data);
    		InorderPrintTree(bt->rchild);
    	}
    }
    
    
    • ·树的结构、操作、遍历及应用
    //存储结构
    //1.双亲表示法(使用顺序存储结构)
    #define MAXSIZE 100
    typedef struct PTNode
    {
        ElemType data;    //数据域
        int parent;    //指向双亲的游标域
    }PTNode;    //定义结点结构体
    typedef struct
    {
        PTNode nodes[MAXSIZE];    //结点数组
        int root;    //指向根结点的游标
        int count;    //结点数
    }PTree;    //定义树结构体
    
    //2.孩子表示法
    #define MAXSIZE 100
    typedef struct CTNode
    {
        int child;    //指向长子的游标域
        struct CTNode *next;    //指向下一个孩子的指针域
    }*ChildPtr;    //定义孩子结点结构体
    typedef struct
    {
        ElemType data;    //数据域
        //同双亲表示法的拓展,这里可以开个指向双亲的指针域
        ChildPtr *firstchild;    //指向长子的指针域
    }CTBox;    //定义表头结构体
    typedef struct
    {
        PTNode nodes[MAXSIZE];    //结点数组
        int root;    //指向根结点的游标
        int count;    //结点数
    }CTree;    //定义树结构体
    
    //3.孩子兄弟表示法
    typedef struct Node
    {
    	ElemType data;
    	int level = 0;
    	int contents = 0;
    	struct Node* bro;				//指向兄弟
    	struct Node* child;				//指向孩子
    }Tnode,* Tree;
    
    //遍历输出
    void printTree(Tree root)
    {
    	int i;
    	if (root == NULL)
    	{
    		return;
    	}
    
    	cout << root->daata << endl;
    	printTree(root->child);
    	printTree(root->bro);
    }
    

    应用:

    #include<iostream>
    #include<string>
    using namespace std;
    
    typedef struct Node
    {
    	string name;						//存储文件或目录名
    	int level = 0;								//确定是几级目录或几级文件,方便输出时确定输出空格数
    	int contents = 0;						//判断是否为目录
    	struct Node* bro;				//指向兄弟
    	struct Node* child;				//指向孩子
    }Tnode,* Tree;
    
    void creatTree(Tree root, string str);				//建树
    void printTree(Tree root);						//先序遍历输出树
    Tree insertNode(Tree root, string str, int flag, int lvl);							//插入结点
    
    int main()
    {
    	int i, j, N, level, isCheck;
    	string str;
    
    	Tree root = new Tnode;		//开辟起始节点及结点的初始化
    	root->contents = 1;
    	root->name = "root";		
    	root->bro = root->child = NULL;
    	root->level = 0;				//root是根目录是0级目录
    	root->contents = 1;				
    
    	cin >> N;
    	for (i = 0; i <= N; i++)
    	{
    		getline(cin, str);
    		creatTree(root, str);
    	}
    
    	printTree(root);	//先序遍历输出树
    
    	return 0;
    }
    
    void creatTree(Tree root, string str)
    {
    	int lvl = 0;				//记录当前目录或文件是几级目录或文件
    	int i, index = 0;			//i用来循环遍历,index记录当前需要截取str片段的起始位置
    	for (i = 0; i < str.size(); i++)
    	{
    		if (str[i] == '\')			//判断是否为目录
    		{	
    			lvl++;
    			root = insertNode(root, str.substr(index, i - index), 1, lvl);
    			index = i + 1;
    		}
    	}
    
    	if (index < str.size())				//如果i<str.size()则意味着读取的一行数据最后一个是文件
    	{
    		lvl++;
    		root = insertNode(root, str.substr(index, str.size() - index), 0, lvl);
    	}
    }
    
    
    
    
    
    Tree insertNode(Tree root, string str, int flag, int lvl)
    {
    	Tree pre = root, ptr;
    	Tree T = new Tnode;
    	T->name = str;					//存入文件或目录名
    	T->bro = T->child = NULL;
    	T->contents = flag;				//确定是文件还是目录
    	T->level = lvl;
    	ptr = pre->child;
    
    	if (root->child == NULL)
    	{
    		root->child = T;
    		return root->child;
    	}	
    
    	while (ptr != NULL && ((ptr->contents > T->contents) || (ptr->contents == T->contents && str > ptr->name)))
    	{
    		pre = ptr;
    		ptr = ptr->bro;
    	}
    	
    	if (ptr == NULL)
    	{
    		T->bro = pre->bro;
    		pre->bro = T;
    		return T;
    	}
    	else if (ptr->name == T->name && ptr->contents == T->contents)
    	{
    		delete T;
    		return ptr;
    	}
    	else
    	{
    		if (pre->name == root->name)    //插在根目录的长子位
    		{
    			T->bro = pre->child;
    			pre->child = T;
    		}
    		else    //正常插入
    		{
    			T->bro = pre->bro;
    			pre->bro = T;
    		}
    
    		return T;
    	}
    }
    
    void printTree(Tree root)
    {
    	int i;
    	if (root == NULL)
    	{
    		return;
    	}
    
    	for (i = 0; i < root->level; i++)
    	{
    		cout << "  ";
    	}
    	cout << root->name << endl;
    	printTree(root->child);
    	printTree(root->bro);
    }
    
    • ·线索二叉树
    //存储结构
    typedef struct BiThrNode {
      TElemType data;                       //结点数据
      struct BiThrNode *lchild, *rchild;    //左右孩子指针
      PointerTag LTag;                      
      PointerTag RTag;                      //左右标志
    }BiThrNode, *BiThrTree;
    
    //线索化的实现
    oid InThreading(BiThrTree B,BiThrTree *pre) {
      if(!B) return;
     
      InThreading(B->lchild,pre);   
     
      if(!B->lchild){                   //没有左孩子 
        B->LTag = Thread;               //修改标志域为前驱线索
        B->lchild = *pre;               //左孩子指向前驱结点
      }
     
      if(!(*pre)->rchild){              //没有右孩子
        (*pre)->RTag = Thread;          //修改标志域为后继线索
        (*pre)->rchild = B;             //前驱右孩子指向当前结点
      }
     
      *pre = B;                         //保持pre指向p的前驱
      InThreading(B->rchild,pre);
    
    
    • ·哈夫曼树、并查集
      哈夫曼树:

    代码实现

    #include <iostream>
    using namespace std;
    typedef struct
    {
        int weight;
        int parent;
        int lchild;
        int rchild;
    }HTNode, * HTree;
    
    
    void Select(HTree HT, int k, int& idx1, int& idx2)
    { 
        int min1 = 10000000, min2 = 10000000, i;
        
        for (i = 1; i <= k; i++)
        {
            if (HT[i].parent == 0 && min1 > HT[i].weight)
            {
                min1 = HT[i].weight;
                idx1 = i;
            }
        }
        HT[idx1].parent = k + 1;
        for (int i = 1; i <= k; i++)
        {
            if (HT[i].parent == 0 && min2 > HT[i].weight)
            {
                min2 = HT[i].weight;
                idx2 = i;
            }
        }
        HT[idx2].parent = i;
        HT[k+1].lchild = idx1;
        HT[k+1].rchild = idx2;
    }
    
    
    void CalculateWPL(HTree& HT, int n)
    {
        int m = 2 * n - 1, idx1, idx2, i, wpl = 0;
    
        if (n < 0)
        {
            return;
        }
    
        for (i = n + 1; i <= m; i++)
        {
            Select(HT, i - 1, idx1, idx2);
    
            HT[i].weight = HT[idx1].weight + HT[idx2].weight;
            wpl += HT[i].weight;
        }
        cout << wpl;
    }
    
    
    
    
    int main()
    {
        int n, i, m;
        cin >> n;
        m = 2 * n - 1;
        HTree HT;
        HT = new HTNode[m + 1];
        for (i = 1; i <= m; i++)
        {
            HT[i].parent = HT[i].lchild = HT[i].rchild = 0;
        }
        for (i = 1; i <= n; i++)
        {
            cin >> HT[i].weight;
        }
        CalculateWPL(HT, n);
    
        return 0;
    }
    
    

    查并集

    代码实现

    #include<iostream>
    using namespace std;
    #define MAXSIZE 30001
    typedef struct node {
        int parent;    //指向双亲的游标
        int length;    //表示朋友圈的长度
    }UFSTree;
    int Find(UFSTree t[], int x);
    void Union(UFSTree t[], int x, int y);
    
    int main()
    {
        int M, N, idx, first, count;
        UFSTree t[MAXSIZE];
        int i, j;
        int max = 0;
    
        cin >> M >> N;
        for ( i = 1; i <= M; i++)
        {
            t[i].length = 0;
            t[i].parent = i;
        }
        for ( i = 0; i < N; i++)
        {
            cin >> count >> first;
            for ( j = 1; j < count; j++)
            {
                cin >> idx;
                Union(t, first, idx);
            }
        }
        for ( i = 1; i <= M; i++)
        {
            idx = Find(t, i);
            t[idx].length++;
            if (t[idx].length > max)
            {
                max = t[idx].length;
            }
        }
        cout << max;
        return 0;
    }
    
    int Find(UFSTree t[], int x)
    {
        int i;
    
        if (t[x].parent == x)
            return t[x].parent;
        t[x].parent = Find(t, t[x].parent);
        return t[x].parent;
    }
    
    void Union(UFSTree t[],int x, int y)
    {
        int idx1, idx2;
    
        idx1 = Find(t, x);
        idx2 = Find(t, y);
        if (idx1 != idx2)
        {
            t[idx2].parent = idx1;
        }
    }
    
    
    

    1.2谈谈你对树的认识及学习体会

     在树这一章节,我们学习的是二叉树的算法。
     树的构建:一种是直接给树的顺序存储结构的字符串,一种是通过先序遍历和中序遍历、或中序遍历和后序遍历来构造树(理解的还比较乱),还有一种哈夫曼树的构造。
     在树中常常会用到递归算法,递归口的设置也是一大难点。
    

    3.阅读代码(0--4分)

    3.1


    3.1.1 该题的设计思路

    先在两端取两个指针,这样底边就达到了最大值,然后再考量两端的边长。然后指针再向内部移动。具体的就是让指向两边中最短边的指针向内移动,如此新的面积才可能更大。

    3.1.2 伪代码

        定义 int 型变量 size并赋初值 height.size()
    
        if size<=0      //即题目中的“容器“不存在
            返回 -1
        end if
    
        定义 int 型变量 i赋初值0, j赋初值size-1,maxArea,newArea均赋初值0   
        while i<j
            计算新面积
            判断新面积和之前的最大面积的大小关系,使最大面积存大的
    
            if i对应的高度比j对应的高度小
                i++
            else
                j++
            end if
        end while
    
        返回 最大面积
    

    3.1.3 运行结果

    3.1.4分析该题目解题优势及难点。

    指针的移动,小的边对应的指针移动才能求出最大容积

    3.2



    3.2.1 该题的设计思路

    该题采用后序遍历的方法,若树为空,则返回NULL。接着递归左子树和右子树。若有结点左、右孩子都为空,且该结点的值为0,则返回NULL,否则返回root

    3.2.2 伪代码

        if root为空
            返回NULL
        end if
    
        递归调用函数,判断对左右孩子进行判断
        
         is 左右孩子均为空且结点的值为0
            返回 NULL 结束循环
        end if
    
        返回 root
    

    3.2.3 运行结果

    3.2.4分析该题目解题优势及难点。

    先序遍历结点并移除0结点

    3.3

    3.3.1 该题的设计思路

    对最小距离的判断,要不停的递归调用自身函数

    3.3.2 伪代码

    void pre(vector<int>& res, TreeNode* root)
    {
        if root不为空
            对左孩子递归调用函数
            将节点的值存入res中
            对右孩子递归调用函数
        end if
    }
    int minDiffInBST(TreeNode* root)
    {
        定义int 型voctor容器res
        以pes和root为参数调用pes函数
        定义int 型voctor容器r
    
        for i=0to res.size()-1
            将res[i + 1] - res[i]存入r
        end for
    
        对r进行排序
    
        返回 r[0]
    }
    

    3.3.3 运行结果

    3.3.4分析该题目解题优势及难点。

    判断两结点之间的距离,并不断比较并返回

    3.4


    3.4.1 该题的设计思路

    vector<vector<int>> zigzagLevelOrder(TreeNode* root)
    {
        调用递归函数
        返回res
    }
    void addVector(TreeNode* root,int level)
    {
        level表示层数,也对应二维数组的第一层索引,
        如果为偶数行
            顺序加入
        如果为奇数行
            数字存到第一个位置
        对左孩子和右孩子分别调用递归函数
    }
    

    3.4.3 运行结果

    3.4.4分析该题目解题优势及难点。

    通过遍历,可以将同一层级的所有节点连接起来。

  • 相关阅读:
    jenkins1—docker快速搭建jenkins环境
    UPC-6616 Small Multiple(BFS广搜&双向队列)
    UPC-5502 打地鼠游戏(贪心&优先队列)
    UPC-5500 经营与开发(贪心&逆推)
    NBUT
    UPC-6690 Transit Tree Path(树上最短路径SPFA)
    UPC-6359 售票(字典树)
    UPC-6358 庭师的利刃(两数与运算最大值)
    HDU-6308 Time Zone(时区转换)
    欧拉函数模板及拓展
  • 原文地址:https://www.cnblogs.com/whb1/p/12685344.html
Copyright © 2011-2022 走看看