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分析该题目解题优势及难点。

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

  • 相关阅读:
    剑指offer-二维数组中的查找
    TF-IDF(term frequency–inverse document frequency)
    Java实现中文字符串的排序功能
    当前课程
    【R】资源整理
    CentOS相关
    【转】Setting up SDL Extension Libraries on MinGW
    【转】Setting up SDL Extension Libraries on Visual Studio 2010 Ultimate
    【转】Setting up SDL Extension Libraries on Code::Blocks 12.11
    【转】Setting up SDL Extension Libraries on Visual Studio 2019 Community
  • 原文地址:https://www.cnblogs.com/whb1/p/12685344.html
Copyright © 2011-2022 走看看