数据结构——树形结构的应用

简介:

1 算数表达式求值


三种遍历方式

①先序遍历次序(前缀式):+ * 3 - 6 2 / 8 2

②中序遍历方式(中缀式):3 * 6 - 2 + 8 / 2

③后序遍历方式(后缀式):3 6 2 - * 8 2 / +

由表达式的三种标识方法,可得到如下结论:

①操作数之间的相对次序不变

②运算符的相对次序不同

③中缀式丢失了括号信息,致使运算的次序不确定

④前缀式的运算规则是:连续出现的两个操作数和在它们之前且紧靠它们的运算符构成一个最小表达式。

⑤后缀式的运算规则是:运算符在式中出现的顺序恰为表达式的运算顺序;每个运算符和在它之前出现且紧靠它的两个操作数构成一个最小表达式。

实现代码:

//BinaryExpTree.h
#pragma once
#include "BTnode.h"
#include <windows.h>
class BinaryExpTree
{
public:
	BinaryExpTree():m_root(NULL){}
	~BinaryExpTree();
	void Create(char ch1[],char ch2[],int);
	int Evaluate();
private:
	BTnode<char>* m_root;
	void _DestroyBT(BTnode<char>* &);
	int _Evaluate(BTnode<char>* &);
	int _Operate(const int&, const char&, const int&);
	void _Create(BTnode<char>* &,char ch1[],char ch2[],int,int,int&);
};
//BinaryExpTree.cpp
#include "BinaryExpTree.h"

BinaryExpTree::~BinaryExpTree()
{
	_DestroyBT(m_root);
}

void BinaryExpTree::Create(char ch1[],char ch2[],int n)
{
	int i = 0;
	_Create(m_root,ch1,ch2,0,n-1,i);
}

void BinaryExpTree::_DestroyBT(BTnode<char>* &p)
{
	if (p)
	{
		_DestroyBT(p->Lchild);
		_DestroyBT(p->Rchild);
		delete p;
	}
}

int BinaryExpTree::Evaluate()
{
	return _Evaluate(m_root);
}

int BinaryExpTree::_Evaluate(BTnode<char>* &T)
{
	if (T)
	{
		if (!T->Lchild && !T->Rchild)
		{
			return T->data - '0';
		}
		return _Operate(_Evaluate(T->Lchild),T->data,_Evaluate(T->Rchild));
	}
}

int BinaryExpTree::_Operate(const int&a, const char& theta, const int&b)
{
	int c;
	switch(theta)
	{
	case '+' : c = a + b; break;
	case '-' : c = a - b; break;
	case '*' : c = a * b; break;
	case '/' : c = a / b; break;
	}
	return c;
}

void BinaryExpTree::_Create(BTnode<char>* &T,char ch1[],char ch2[],int low,int high,int& k)
{
	int i;
	if (low > high)
	{
		T = NULL;
	}
	else
	{
		T = new BTnode<char>;
		T->data = ch1[k];
		for (i = low; i <= high && ch2[i]!= ch1[k]; i++);
		k++;
		_Create(T->Lchild,ch1,ch2,low,i-1,k);
		_Create(T->Rchild,ch1,ch2,i+1,high,k);
	}
}
//main.cpp
#include <iostream>
#include <fstream>
#include "BinaryExpTree.h"
using namespace std;

void main(int argc, char* argv[])
{
	BinaryExpTree bt;
	char pch[256],ich[256];
	cout<<"请按二叉表达式树的前缀表示输入字符串:"<<endl;
	cin>>pch;
	cout<<"请按二叉表达式树的中缀表示输入字符串:"<<endl;
	cin>>ich;
	int i = 0;
	while (pch[i])
	{
		i++;
	}
	bt.Create(pch,ich,i);
	cout<<"表达式按后缀求值的结果为:"<<bt.Evaluate()<<endl;
	system("pause");
}

2 等价问题

静态树表节点的双亲表示法如下:

struct PTnode
{
	char data;
	int parent;
};
求解等价问题的类描述如下:
//MEset.h
#pragma once
#include "PTnode.h"
class MEset
{
public:
	MEset(int n):m_len(0),m_size(n){m_nodes = new PTnode[n];}
	~MEset(){delete [] m_nodes;}
	bool Create(char[],const int&);
	void Display();
	int LocateElem(const char&);
	int FindRoot(const int&);
	void Merge(const int&, const int&);
	void EffMerge(const int&, const int&);
private:
	int m_len;
	int m_size;
	PTnode* m_nodes;
};
求解等价问题的类定义如下:
//MEset.cpp
#include "MEset.h"
#include "iostream"
bool MEset::Create(char ch[],const int& n)
{
	if (n > m_size)
	{
		return false;
	}
	int i = 0;
	while (i < n)
	{
		m_nodes[i].data = ch[i];
		m_nodes[i].parent = -1;
		i++;
	}
	m_len = n;
	return true;
}

int MEset::LocateElem(const char& e)
{
	for (int i = 0; i < m_len; i++)
	{
		if (m_nodes[i].data == e)
		{
			return i;
		}
	}
	return -1;
}

int MEset::FindRoot(const int& i)
{
	int k;
	for (k = i; m_nodes[k].parent >= 0; k = m_nodes[k].parent);
	return k;
}

void MEset::Merge(const int& i, const int& j)
{
	m_nodes[i].parent = j;
}

//子树的根结点的parent域存储子树中所含数据元素个数的负值,在合并时
//令成员少的子树的根结点之parent域指向成员多的子树的跟
void MEset::EffMerge(const int& i, const int& j)
{
	if (m_nodes[i].parent > m_nodes[j].parent)
	{
		m_nodes[j].parent += m_nodes[i].parent;
		m_nodes[i].parent = j;
	}
	else
	{
		m_nodes[i].parent += m_nodes[j].parent;
		m_nodes[j].parent = i;
	}
}

void MEset::Display()
{
	std::cout<<"位置   "<<"data   "<<"parent   "<<std::endl;
	for (int i = 0; i < m_len; i++)
	{
		std::cout<<"  "<<i<<"    "<<m_nodes[i].data
			<<"    "<<m_nodes[i].parent<<std::endl;
	}
}
主函数如下:
//main.cpp
#include <iostream>
#include <fstream>
#include "MEset.h"
using namespace std;

void main(int argc, char* argv[])
{
	ifstream cin("input.txt");
	int n,m,i,j,k=1,r1,r2;
	char c,d,ch[256];
	cout<<"请输入集合中元素的个数:"<<endl;
	cin>>n;
	MEset a(n);
	cout<<"请输入"<<n<<"个数据元素至集合a:"<<endl;
	for (int i = 0; i < n; i++)
	{
		cin>>ch[i];
	}
	cout<<endl;
	a.Create(ch,n);
	a.Display();
	cout<<endl;
	cout<<"请输入等价关系的序偶对个数:"<<endl;
	cin>>m;
	cout<<endl;

	while (k <= m)
	{
		cout<<"请输入一个等价关系:"<<endl;
		cin>>c>>d;
		i = a.LocateElem(c);
		j = a.LocateElem(d);
		if (i < 0 || j < 0)
		{
			cout<<"输入有误,请重输!"<<endl;
		}
		else
		{
			r1 = a.FindRoot(i);
			r2 = a.FindRoot(j);
			if (r1 != r2)
			{
				cout<<c<<"和"<<d<<"不是同属于一个等价类"<<endl;
				a.EffMerge(r1,r2);
			}
			else
			{
				cout<<c<<"和"<<d<<"是同一个等价类"<<endl;
			}
			k++;
		}
	}

	cout<<endl;
	a.Display();
	cout<<endl;
	system("pause");
}
输入:


输出:


转载:http://blog.csdn.net/foreverling/article/details/43236263

目录
相关文章
|
3月前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
56 1
|
3月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
96 4
|
3月前
|
机器学习/深度学习 存储 人工智能
数据结构在实际开发中的广泛应用
【10月更文挑战第20天】数据结构是软件开发的基础,它们贯穿于各种应用场景中,为解决实际问题提供了有力的支持。不同的数据结构具有不同的特点和优势,开发者需要根据具体需求选择合适的数据结构,以实现高效、可靠的程序设计。
226 63
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
74 5
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
68 1
|
2月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
46 5
|
3月前
探索数据结构:队列的的实现与应用
探索数据结构:队列的的实现与应用
|
3月前
|
存储
探索数据结构:单链表的实践和应用
探索数据结构:单链表的实践和应用
|
3月前
|
存储 测试技术
探索数据结构:顺序表的实现与应用
探索数据结构:顺序表的实现与应用