数据结构与算法(第三章-1)

这篇博客介绍了二叉树的实现,包括层序遍历的队列结构,以及二叉树的先序、中序、后序和层序遍历。此外,还讲解了哈夫曼树和编码的构建过程,使用C++实现。博客中提到了编程知识,如`vector`、`map`的使用,特别是`vector<bool>`的空间优化特性,并强调`vector<bool>`不是一个标准容器。最后,展示了如何构建哈夫曼树并生成编码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

二叉树的实现

哈夫曼树与编码的实现 

学到的编程知识

(1)vector 

(2)vector

vector 不是一个容器   

(3)   map a,value>


二叉树的实现

#include<iostream>
using namespace std;
#include<iostream>
using namespace std;
template<typename T>//层序遍历时需要使用的队列 
struct QNode
{
	T elem;
	QNode*next;
};
template<typename T>
class LinkQueue
{
	QNode<T> *front,*rear;
public:
    LinkQueue():front(NULL),rear(NULL){};
	~LinkQueue() 
	{
		QNode<T>*p;
		while(!front)
		{
			p=front;front=front->next;delete p;
		}
	}
	bool IsEmpty()const {return front==NULL;}
    int Length()const 
	{
	    QNode<T>* p=front;
		int i=0;
		while(p)
		{i++;p=p->next;}
		return i;
	}
	void InQueue(T&e)
	{
		if(IsEmpty())
		{
		    front=rear=new QNode<T>;
		    front->elem=e;
		    front->next=NULL;
		}
		else
		{
			QNode<T>*node=new QNode<T>;
			node->elem=e;
			node->next=NULL;
	    	rear=rear->next=node;
		}	
	}
	T OutQueue()
	{
		if(IsEmpty()) {cout<<"队列为空"<<endl;exit(0); }
		T e=front->elem;
		QNode<T>*p=front;
		front=front->next;
		if(front==NULL)  rear=NULL;
		delete p;
		return e;
	}	 
 };
template<class T>
class BTree;
template<class T>
class BTNode//二叉树节点类 
{
	friend class BTree<T>;
//	friend class BSTree<T>;
	T data;
	BTNode<T>*left;
	BTNode<T>*right;
public:
	BTNode();
	BTNode(const T&e){data=e;}
	BTNode(const T&e,BTNode<T>*l,BTNode<T>*r){data=e; left=l; right=r;}//给定值和左右指针的构造函数 
	~BTNode(){};
	T value() const {return data;}
	BTNode<T>*lch()const{return left;}
	BTNode<T>*rch()const{return right;}
	void setlch(BTNode<T>*l){left=l;}
	void setrch(BTNode<T>*r){right=r;}	
	void servalue(const T&val){data=val;}	
};
template<class T>
class BTree
{
protected:
	BTNode<T>*root;
public:
	BTree(){root=NULL;}
	BTree(BTNode<T>*r){root=r;}
	~BTree(){DeleteBTree(root);}
	DeleteBTree(BTNode<T>*t)
	{
		if(t)
		{
			BTNode<T>*l=t->left;
			BTNode<T>*r=t->right;
			delete t;
			DeleteBTree(l);
			DeleteBTree(r);
		}
		return 0;
	}
	bool IsEmpty()const{return root==NULL;}
	void visit(const T&data){cout<<data<<" ";}//不可直接在外部访问私有成员 
	BTNode<T>*&Root(){return root;}
	BTNode<T>*ls(BTNode<T>*c){return c->left;}
	BTNode<T>*rs(BTNode<T>*c){return c->right;}
	void create(const T&data,BTree<T>&leftTree,BTree<T>&rightTree);
	void create(BTNode<T>*&r)//先序遍历构造二叉树 
	{
		T ch;
		cin>>ch;
		if(ch=='#') r=NULL;
		else{
			r=new BTNode<T>(ch);
			create(r->left);
			create(r->right);
		} 
	}
	void PreOrder(BTNode<T>*root)
	{
		if(root==NULL) return;
		visit(root->value());
		PreOrder(root->lch);
		PreOrder(root->rch);
	} 
	void InOrder(BTNode<T>*root)
	{
		if(root==NULL) return;
		InOrder(root->lch);
		visit(root->value());
	    InOrder(root->rch);
	} 
	void PostOrder(BTNode<T>*root)
	{
		if(root==NULL) return;
	    PostOrder(root->lch);
		PostOrder(root->rch);
		visit(root->value());
	} 
	void LevelOrder(BTNode<T>*root)
	{
		LinkQueue<BTNode<T>*>t;//队列节点类型为二叉树节点的指针 
		BTNode<T>*p=root;
		if(p) t.InQueue(p);
		while(!t.IsEmpty())
		{
			p=t.OutQueue();
			visit(p->value());
			if(p->lch())
			  t.InQueue(p->lch());
			if(p->rch())
			  t.InQueue(p->rch());
		}
	}
};

哈夫曼树与编码的实现 

#include<iostream>
#include<queue>
#include<vector>
#include<map>
using namespace std;
template<class T>
class HTree;
template<class T>
class HTNode//二叉树节点类 
{
	friend class HTree<T>;
//	friend class BSTree<T>;
	T data;
	HTNode<T>*left;
	HTNode<T>*right;
	int wgt;
public:
	HTNode();
	HTNode(const T&e,int w){data=e;left=NULL;right=NULL;w=wgt;}
	HTNode(HTNode<T>*l,HTNode<T>*r,int w){ left=l; right=r; wgt=w;}//给定值和左右指针的构造函数 
	~HTNode(){};
	T& value() {return data;}
	HTNode<T>*lch()const{return left;}
	HTNode<T>*rch()const{return right;}	
	bool Isleaf(){return !left&&!right;}	
};
template<class T>
class HTree
{
protected:
	HTNode<T>*root;	
public:
	HTree(T e,int w) { root=new HTNode<T>(e,w); }
	HTree(int w,HTree<T>*l,HTree<T>*r){ root=new HTNode<T>(l->root,r->root,l->weight()+r->weight());}
	int weight(){return root->wgt;}
	~HTree(){DeleteHTree(root);}
	DeleteHTree(HTNode<T>*t)
	{
		if(t)
		{
			HTNode<T>*l=t->left;
			HTNode<T>*r=t->right;
			delete t;
			DeleteHTree(l);
			DeleteHTree(r);
		}
		return 0;
	}
    HTNode<T>*Root(){return root;}
};
template<class T>
class cmp{
public:
	bool operator()(HTree<T>*x,HTree<T>*y)
	{
		return x->weight()<y->weight();
	}
};
template<class T>
HTree<T>*BuildHTree(T elem[],int weight[],int n)
{
	priority_queue<HTree<T>*,vector<HTree<T>*>,cmp<T> > q;
	for(int i=0;i<n;i++)
    q.push(new HTree<T>(elem[i],weight[i]));
    while(q.size()>1)
    {
    	HTree<T>*l=q.top();
    	q.pop();
    	HTree<T>*r=q.top();
    	q.pop();
    	HTree<T>*p=new HTree<T>(l->weight()+r->weight(),l,r);
    	q.push(p);
	}
	return q.top();
}
typedef vector<bool>HCode;
map<char,HCode>HDic;
template<class T>
void Huffcode(HTNode<T>*r,HCode curr)
{
	if(r->Isleaf())
	{
		HDic[r->value()]=curr;
		return;
	}
	HCode lc=curr;
	HCode rc=curr;
	lc.push_back(false);
	rc.push_back(true);
	Huffcode(r->lch(),lc);
	Huffcode(r->rch(),rc);	
}
int main()
{   
    cout<<"输入编码数";
    int n;
    cin>>n;
	cout<<"输入要编码的字母"; 
	char* ele=new char[n];
	for(int i=0;i<n;i++)
	cin>>ele[i];
	cout<<"输入对应权值";
	int*w=new int[n];
	for(int i=0;i<n;i++)
	cin>>w[i];
	HTree<char>*r=BuildHTree<char>( ele,w,n);
	HCode curr;
    Huffcode<char>(r->Root(),curr);
    cout<<"输入要查询的字母";
    char a;
	cin>>a; 
    HCode c=HDic[a];
	int nSize = c.size();   
    for(int i=0;i<nSize;i++)    
    cout<<c[i]<<" ";   
	return 0;     
}

学到的编程知识

(1)vector<T> 

https://www.cnblogs.com/Nonono-nw/p/3462183.html

(2)vector<bool>

vector <bool>是为了当元素都为bool类型时,优化空间所产生的vector<T>的特化版,主要解决的就是节省空间的问题
       节省空间的方法是,按照一个二进制位来存储,而不是一个字节。一个字节可以存八个bool值,极大的节省了空间,而且vector <bool>并没有要求底层的存储必须是连续的空间。

vector <bool>提高空间效率的同时降低了时间效率
       因为它是按位存的,一个字节存八个bool值,但是要知道第i个bool值的真假,需要进行位运算,效率就会低一些,存的bool值越多花费的时间就越长,这是典型的以时间换空间的策略。

vector <bool>不是一个容器
   

(3)   map<key,value> a

一、 map的特性
所有元素都会根据元素的减值自动被排序。
map的所有元素都是pair,同时拥有实值(value)和键值(key)。
pair的第一个元素会被视为键值,第二个元素会被视为实值。
map不允许两个元素拥有相同的键值。
头文件:#include< map >
二、map的基本构造函数类型
 

 map<string , int >strMap;

 map<int ,string >intMap;

 map<sring, char>strMap;

 map< char ,string>charMap;

 map<char ,int>charMap;

 map<int ,char >intMap;


三、map的基本操作函数:

begin()     //返回指向map头部的迭代器

clear()    //删除所有元素

count()     //返回指定元素出现的次数

empty()     //如果map为空则返回true

end()      //返回指向map末尾的迭代器

equal_range()  //返回特殊条目的迭代器对

erase()     //删除一个元素

find()      //查找一个元素。查的是 健
//当所查找的关键key出现时,它返回数据所在对象的位置,如果沒有,返回iter与end()函数的值相同。

 
get_allocator() //返回map的配置器

insert()     //插入元素

key_comp()    //返回比较元素key的函数

lower_bound()  //返回键值>=给定元素的第一个位置

max_size()    //返回可以容纳的最大元素个数

rbegin()     //返回一个指向map尾部的逆向迭代器

rend()      //返回一个指向map头部的逆向迭代器

size()      //返回map中元素的个数

swap()      //交换两个map

upper_bound()   //返回键值>给定元素的第一个位置

value_comp()   //返回比较元素value的函数


四、map添加数据

map<int ,string> maplive;

pair<int,string> value(1,"a");maplive.insert(value);
//等价于maplive.insert(pair<int,string>(1,"a"));

maplive.insert(map<int,string>::value_type(1,"a"));

maplive[1]="a";//map中最简单最常用的插入添加!


版权声明:优快云博主「杨青葱」的原创,遵循CC 4.0 BY-SA版权协议,转载请附上
原文链接:https://blog.youkuaiyun.com/LUSH_BOY/article/details/113483998

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值