数据结构学习笔记(八)字典、及其线性表描述

一、字典

        字典是一些形如(k,v)的数对所组成的集合,其中k是关键字,v是与关键字k对应的值。任意两个数对,其关键字都不相等。比如一个选修某一课程的名单是一个字典结构,关键字是学号,对应的值包含名字、性别、分数等等信息。有关字典的操作有:

  • 确定字典是否为空
  • 确定字典有多少数对
  • 寻找一个指定了关键字的数对
  • 插入一个数对
  • 删除一个指定了关键字的数对
        一个多重字典和上诉字典类似,只是两个或更多的数对可以具有相同的关键字。比如一个号码本是一个多重字典,因为会存在重名的情况。编译器的符号表也是一个多重字典。在一个多重字典中进行查找,需要明确是查找任意一个具备给定关键字的数对,还是查找所有具有给定关键字的数对。删除操作在找到所有具有给定关键字的数对后,要由用户确定具体删除哪一个或者全部删除。

        此外还要注意,有时候我们需要另一形式的删除操作,即删除在某一时间之后插入的所有数对。

        字典的抽象基类如下:

#pragma once 
using namespace std;
//字典的抽象基类
template 
class dictionary
{
public:
	virtual ~dictionary(){}
	virtual bool empty() const = 0;//判断是否为空
	virtual int size() const = 0;//返回字典的大小
	virtual pair* find(const K&) const = 0;//查找某一元素
	virtual void erase(const K&) = 0;//删除某一元素
	virtual void insert(const pair&) = 0;//插入某一元素
};


        我们可以使用有序数组、有序链表、跳表和散列表来描述字典,他们的渐进性能见下图,此外,我们还可以使用搜索树以及平衡树来描述。

        数据结构学习笔记(八)字典、及其线性表描述_第1张图片

二、线性表描述

      字典可以保存在线性表(p0,p1。。。)中,线性表是按照关键字递增的次序来排列数对的。我们知道线性表可以用数组和链表表示,着了使用链表进行存储。在使用线性链表描述字典时,每一个节点包含数据域element代表一个数对和一个指针域next指向下一个元素。查找、插入和删除等操作,在线性表一章详细讨论过,具体的实现代码如下:

//字典的有序链表实现
#pragma once
#include
#include"dictionary.h"

using namespace std;

//链表的每一个节点
template 
struct pairNode
{
	typedef pair  pairType;
	pairType element;//节点的值域
	pairNode *next;//节点的指针域

	pairNode(const pairType& thePair) :element(thePair){}
	pairNode(const pairType& thePair, pairNode* theNext):element(thePair){next = theNext;	}
};

//有序链表描述字典结构
template
class sortedChain :public dictionary
{
public:
	//构造函数和析构函数
	sortedChain(){ firstNode = NULL; dSize = 0; }
	~sortedChain()
	{
		while (firstNode != NULL)
		{
			pairNode* nextNode = firstNode->next;
			delete firstNode;
			firstNode = nextNode;
		}
	}

	//成员函数
	bool empty()const { return dSize == 0; }
	int size() const { return dSize; }
	pair* find(const K&)const;
	void erase(const K&);
	void insert(const pair&);
	void output(ostream& out) const;//用于输出

private:
	pairNode* firstNode;
	int dSize;
};

//查找字典中某一元素
template
pair* sortedChain::find(const K& theKey)const
{
	pairNode* currentNode = firstNode;
	//找出该节点的位置
	while (currentNode != NULL&¤tNode->element.first != theKey)
		currentNode = currentNode->next;
	//确定该节点是寻找的节点
	if (currentNode != NULL&¤tNode->element.first == theKey)
		return ¤tNode->element;
	//没有该节点返回空
	return NULL;
}

//插入某一元素到字典中
template
void sortedChain::insert(const pair& thePair)
{
	pairNode *p = firstNode, *tp = NULL;//tp用来跟踪p

	//移动tp,thePair插入到tp后面(有序链表)
	while (p != NULL&&p->element.first < thePair.first)
	{
		tp = p;
		p = p->next;
	}
	//如果字典中有该词,更新
	if (p != NULL&&p->element.first == thePair.first)
	{
		p->element.second = thePair.second; return;
	}
	//如果字典无该词,添加
	pairNode* newNode = new pairNode(thePair, p);
	if (tp == NULL) firstNode = newNode;
	else tp->next = newNode;
	dSize++;
	return;
}

//删除,某一元素
template
void sortedChain::erase(const K& theKey)
{
	pairNode *p = firstNode,*tp = NULL; // tp跟踪p

	// 查找元素的位置
	while (p != NULL && p->element.first < theKey)
	{
		tp = p;
		p = p->next;
	}

	// 如果有,删除
	if (p != NULL && p->element.first == theKey)
	{
		if (tp == NULL) firstNode = p->next;  // p 是首节点
		else tp->next = p->next;

		delete p;
		dSize--;
	}
}

//输出
template
void sortedChain::output(ostream& out) const
{
	for (pairNode* currentNode = firstNode;currentNode != NULL;currentNode = currentNode->next)
		out << currentNode->element.first << " "<< currentNode->element.second << "  ";
}
template 
ostream& operator<<(ostream& out, const sortedChain& x)
{
	x.output(out); return out;
}


测试代码:

#include
#include "sortedchain.h"

using namespace std;

void main()
{
	sortedChain z;
	pair p;

	// test insert
	p.first = 2; p.second = 10;
	z.insert(p);
	p.first = 10; p.second = 50;
	z.insert(p);
	p.first = 6; p.second = 30;
	z.insert(p);
	p.first = 8; p.second = 40;
	z.insert(p);
	p.first = 1; p.second = 5;
	z.insert(p);
	p.first = 12; p.second = 60;
	z.insert(p);
	cout << "The chain is " << z << endl;
	cout << "Its size is " << z.size() << endl;

	// test find
	cout << "Element associated with 1 is " << z.find(1)->second << endl;
	cout << "Element associated with 6 is " << z.find(6)->second << endl;
	cout << "Element associated with 12 is " << z.find(12)->second << endl;

	// test erase
	z.erase(1);
	z.erase(6);
	z.erase(12);
	cout << "Deleted 1, 6, 12" << endl;
	cout << "The chain is " << z << endl;
	cout << "Its size is " << z.size() << endl;
}


你可能感兴趣的:(数据结构)