图的邻接矩阵
深度优先遍历算法(递归)
输出(输出+visited)
for(遍历)
{
if(是边且未被访问)
递归
}
广度优先遍历算法(队列)
输出(输出+visited)
入列
while(队非空)
{
w=出列的值
for(遍历)
{
if(是边且未被访问)
{
输出(输出+visited)
入列
}
}
}
实现
#include <iostream>
#include <string>
using namespace std;
//循环队列类
const int QueueSize = 100; //循环队列的最大长度
template <class T> //定义模板类CirQueue
class CirQueue
{
public:
CirQueue(); //构造函数,置空队
~CirQueue(); //析构函数
void EnQueue(T x); //将元素x入队
T DeQueue(); //将队头元素出队
T GetQueue(); //取队头元素(并不删除)
bool Empty(); //判断队列是否为空
bool Full();
private:
T data[QueueSize]; //存放队列元素的数组
int front, rear; //队头和队尾指针,分别指向队头元素的前一个位置和队尾元素的位置
};
//功 能:初始化空队列
template <class T>
CirQueue<T>::CirQueue()
{
front = rear = 0;
}
// 功 能:销毁队列
template <class T>
CirQueue<T>::~CirQueue()
{
}
//功 能:元素x入队
template <class T>
void CirQueue<T>::EnQueue(T x)
{
if (Full()) throw "Overflow";
rear = (rear + 1) % QueueSize; //队尾指针在循环意义下加1
data[rear] = x; //在队尾处插入元素
}
//功 能:队头元素出队,返回值为出队元素
template <class T>
T CirQueue<T>::DeQueue()
{
if (Empty()) throw "Downflow";
front = (front + 1) % QueueSize; //队头指针在循环意义下加1
return data[front]; //读取并返回出队前的队头元素,注意队头指针
}
//指向队头元素的前一个位置
// 功 能:获取队头元素
template <class T>
T CirQueue<T>::GetQueue()
{
int i;
if (Empty()) throw "Downflow";
i = (front + 1) % QueueSize; //注意不要给队头指针赋值
return data[i];
}
// 功 能:判断队列是否为空,若空返回true,否则返回false
template <class T>
bool CirQueue<T>::Empty()
{
return front == rear;
}
//功 能:判断队列是否满,若满返回true,否则false
template <class T>
bool CirQueue<T>::Full()
{
return (rear + 1) % QueueSize == front;
}
//Class MGraph
const int MaxSize = 20; //图中最多顶点个数
int visited[MaxSize]; //访问标志数组(0表示未访问,1表示已访问)
template <class T>
class MGraph
{
public:
MGraph(T a[], int n, int e); //构造函数,初始化具有n个顶点,e条边的图
void DispMGraph(); //输出图中顶点值和矩阵值
void DFSTraverse(int v); // 从v顶点出发深度优先遍历图(一个连通子图)
void BFSTraverse(int v); // 从v顶点出发广度优先遍历图(一个连通子图)
private:
T vertex[MaxSize]; //存放图中顶点信息的数组
int arc[MaxSize][MaxSize]; //存放图中顶点关系(边)的数组
int vertexNum, arcNum; //图的顶点数和边数
};
//构造一个邻接矩阵存储的无向图
template <class T>
MGraph<T>::MGraph(T a[], int n, int e)
{
vertexNum = n; //顶点数
arcNum = e; //边数
int i, j, k;
for (i = 0; i < vertexNum; i++)
vertex[i] = a[i]; //顶点值
for (i = 0; i < vertexNum; i++) //初始化邻接矩阵值为0(顶点间无边)
for (j = 0; j < vertexNum; j++)
arc[i][j] = 0;
for (k = 0; k < arcNum; k++) //依次输入e条边
{
cin >> i >> j; //输入各条边依附的两个顶点的序号
arc[i][j] = 1; //置有边标志
arc[j][i] = 1;
}
}
//输出图中所有顶点信息,和边信息
template <class T>
void MGraph<T>::DispMGraph()
{
int i, j;
cout << " ";
for (i = 0; i < vertexNum; i++)
cout << vertex[i] << " ";//输出图中所有的顶点
cout << endl;
for (i = 0; i < vertexNum; i++)
{
cout << vertex[i] << " ";
for (j = 0; j < vertexNum; j++)
cout << arc[i][j] << " "; //输出边值(0/1)
cout << endl;
}
}
//在此处实现深度优先遍历算法
template <class T>
void MGraph<T>::DFSTraverse(int v)
{
cout << vertex[v] << " ";
visited[v] = 1;
for (int j = 0; j < vertexNum; j++)
{
if (arc[v][j] == 1 && visited[j] == 0)
{
DFSTraverse(j);
}
}
}
//在此处实现广度优先遍历算法
template <class T>
void MGraph<T>::BFSTraverse(int v)
{
int Q[MaxSize],w,j;
int front = -1, rear = -1;
cout << vertex[v] << " ";
visited[v] = 1;
Q[++rear] = v;
while (rear != front)
{
w = Q[++front];
for (j = 0; j < vertexNum; j++)
{
if (visited[j] == 0 && arc[w][j] == 1)
{
cout << vertex[j]<<" ";
visited[j] = 1;
Q[++rear] = j;
}
}
}
}
int main()
{
string a[] = { "A","B","C","D","E","F","G","H","I","J","K","L","M","N" }; //顶点信息
int i, n, e;
cin >> n >> e; //输入顶点个数和边个数
MGraph<string> G(a, n, e);
G.DispMGraph();
for (i = 0; i < n; i++)
visited[i] = 0;
cout << "DFS:";
G.DFSTraverse(0);
cout << endl;
for (i = 0; i < n; i++)
visited[i] = 0;
cout << "BFS:";
G.BFSTraverse(0);
return 0;
}
邻接表1(有向图)
计算出度入度
用两个边列表指针p,q进行遍历
实现
#include <iostream>
#include <string>
using namespace std;
const int MaxSize = 20; // 顶点个数的最大值
int visited[MaxSize]; //访问标志数组(0表示未访问,1表示已访问)
//定义边表结点
struct ArcNode
{
int adjvex; //邻接点的序号
ArcNode* next; //指向下一个边结点的指针
};
//定义顶点表结点
template <class T>
struct VertexNode
{
T vertex; //顶点的名称
ArcNode* firstedge; //指向第一个边表结点的头指针
};
//邻接表类
template <class T>
class ALGraph
{
public:
ALGraph(T a[], int n, int e); //构造函数,初始化一个有n个顶点e条边的图
~ALGraph(); //析构函数,释放邻接表中各边表结点的存储空间
void DispALGraph(); //输出邻接表
void CountInD(int ind[]); //计算各个顶点的入度,存储在ind中
void CountOutD(int outd[]); //计算各个顶点的出度,存储在outd中
private:
VertexNode<T> adjlist[MaxSize]; //存放顶点表的数组
int vertexNum, arcNum; //图的顶点数和边数
};
/*
*前置条件:图不存在
*输 入:无
*功 能:图的初始化
*输 出:无
*后置条件:得到一个无向图
*/
template <class T>
ALGraph<T>::ALGraph(T a[], int n, int e)
{
arcNum = e; //边数
vertexNum = n; //顶点数
int i, j;
for (i = 0; i < vertexNum; i++)
{
adjlist[i].vertex = a[i];
adjlist[i].firstedge = NULL;
}
for (int k = 0; k < arcNum; k++) //依次输入每一条边,并在相应边表中插入结点
{
cin >> i >> j; //输入边所依附的两个顶点的序号
ArcNode* s = new ArcNode;
s->adjvex = j; //生成一个边表结点s
s->next = adjlist[i].firstedge; //将结点s插入到i号表的头结点之后
adjlist[i].firstedge = s;
}
}
/* 前置条件:图已存在
* 输 入:无
* 功 能:销毁图
* 输 出:无
* 后置条件:释放图所占用的存储空间
*/
template <class T>
ALGraph<T>::~ALGraph()
{
for (int i = 0; i < vertexNum; i++)
{
ArcNode* p = adjlist[i].firstedge;
while (p != NULL) //循环删除
{
adjlist[i].firstedge = p->next;
delete p; //释放结点空间
p = adjlist[i].firstedge;
}
}
}
/*
*前置条件:图已存在
*输 入:无
*功 能:输出图中所有顶点及边的数据信息
*输 出:图中所有顶点及边的数据信息
*后置条件:图保持不变
*/
template <class T>
void ALGraph<T>::DispALGraph()
{
int i;
ArcNode* p;
cout << "Graph adjlist:\n";
for (i = 0; i < vertexNum; i++) {
cout << i << " " << adjlist[i].vertex << " "; //输出图中顶点的序号i及值
for (p = adjlist[i].firstedge; p; p = p->next)
cout << p->adjvex << " "; //输出i号顶点的邻接点的序号
cout << endl;
}
}
//计算各个顶点的入度
template <class T>
void ALGraph<T>::CountInD(int ind[])
{
for (int i = 0; i < vertexNum; i++)
{
ind[i] = 0;
}
ArcNode* p = NULL;
ArcNode* q = NULL;
int w;
for (int i = 0; i < vertexNum; i++)
{
p = adjlist[i].firstedge;
q = adjlist[i].firstedge;
while (p)
{
//cout << endl << 1 << endl;
w = p->adjvex;
ind[w] += 1;
q = p->next;
p = q;
}
}
}
//计算各个顶点的出度
template <class T>
void ALGraph<T>::CountOutD(int outd[])
{
int count = 0;
ArcNode* p = NULL;
ArcNode* q = NULL;
for (int i = 0; i < vertexNum; i++)
{
count = 0;
p = adjlist[i].firstedge;
q = adjlist[i].firstedge;
while (p)
{
//cout << endl <<1<< endl;
count++;
q = p->next;
p = q;
}
outd[i] = count;
//cout <<endl<< "count:" << count << endl;
}
}
int main()
{
string a[] = { "A","B","C","D","E","F","G","H","I","J","K","L","M","N" }; //顶点信息
int i, n, e;
cin >> n >> e; //输入顶点个数和边个数
ALGraph<string> G(a, n, e);
G.DispALGraph();
int ind[MaxSize];
cout << "Indegree:";
G.CountInD(ind);
for (i = 0; i < n; i++)
cout << ind[i] << " ";// 输出各个顶点的入度
cout << endl;
int outd[MaxSize];
cout << "OutDegree:";
G.CountOutD(outd);
for (i = 0; i < n; i++)
cout << outd[i] << " "; // 输出各个顶点的出度
return 0;
}
邻接表2(无向图)
深度优先遍历算法(递归)
先输出当前元素
用while遍历与当前元素相连且未被访问过的元素,进行递归
广度优先遍历算法
输出 入列
队列不为空为大前提循环
出列
找与当前元素相连且未被访问过的元素入列
//graphmain.cpp
#include <iostream>
#include <string>
using namespace std;
//循环队列类
const int QueueSize = 100; //循环队列的最大长度
template <class T> //定义模板类CirQueue
class CirQueue
{
public:
CirQueue(); //构造函数,置空队
~CirQueue(); //析构函数
void EnQueue(T x); //将元素x入队
T DeQueue(); //将队头元素出队
T GetQueue(); //取队头元素(并不删除)
bool Empty(); //判断队列是否为空
bool Full();
private:
T data[QueueSize]; //存放队列元素的数组
int front, rear; //队头和队尾指针,分别指向队头元素的前一个位置和队尾元素的位置
};
//功 能:初始化空队列
template <class T>
CirQueue<T>::CirQueue()
{
front = rear = 0;
}
// 功 能:销毁队列
template <class T>
CirQueue<T>::~CirQueue()
{
}
//功 能:元素x入队
template <class T>
void CirQueue<T>::EnQueue(T x)
{
if (Full()) throw "Overflow";
rear = (rear + 1) % QueueSize; //队尾指针在循环意义下加1
data[rear] = x; //在队尾处插入元素
}
//功 能:队头元素出队,返回值为出队元素
template <class T>
T CirQueue<T>::DeQueue()
{
if (Empty()) throw "Downflow";
front = (front + 1) % QueueSize; //队头指针在循环意义下加1
return data[front]; //读取并返回出队前的队头元素,注意队头指针
}
//指向队头元素的前一个位置
// 功 能:获取队头元素
template <class T>
T CirQueue<T>::GetQueue()
{
int i;
if (Empty()) throw "Downflow";
i = (front + 1) % QueueSize; //注意不要给队头指针赋值
return data[i];
}
// 功 能:判断队列是否为空,若空返回true,否则返回false
template <class T>
bool CirQueue<T>::Empty()
{
return front == rear;
}
//功 能:判断队列是否满,若满返回true,否则false
template <class T>
bool CirQueue<T>::Full()
{
return (rear + 1) % QueueSize == front;
}
const int MaxSize = 20; // 顶点个数的最大值
int visited[MaxSize]; //访问标志数组(0表示未访问,1表示已访问)
//定义边表结点
struct ArcNode
{
int adjvex; //邻接点的序号
ArcNode* next; //指向下一个边结点的指针
};
//定义顶点表结点
template <class T>
struct VertexNode
{
T vertex; //顶点的名称
ArcNode* firstedge; //指向第一个边表结点的头指针
};
//邻接表类
template <class T>
class ALGraph
{
public:
ALGraph(T a[], int n, int e); //构造函数,初始化一个有n个顶点e条边的图
~ALGraph(); //析构函数,释放邻接表中各边表结点的存储空间
void DispALGraph(); //输出邻接表
int Count(); //计算连通分量个数,返回值为连通分量的个数(请大家自己测试)
void DFSTraverse(int v); //深度优先遍历图
void BFSTraverse(int v); //深度优先遍历图
private:
VertexNode<T> adjlist[MaxSize]; //存放顶点表的数组
int vertexNum, arcNum; //图的顶点数和边数
};
/*
*前置条件:图不存在
*输 入:无
*功 能:图的初始化
*输 出:无
*后置条件:得到一个无向图
*/
template <class T>
ALGraph<T>::ALGraph(T a[], int n, int e)
{
arcNum = e; //边数
vertexNum = n; //顶点数
int i, j;
for (i = 0; i < vertexNum; i++)
{
adjlist[i].vertex = a[i];
adjlist[i].firstedge = NULL;
}
for (int k = 0; k < arcNum; k++) //依次输入每一条边,并在相应边表中插入结点
{
cin >> i >> j; //输入边所依附的两个顶点的序号
ArcNode* s = new ArcNode;
s->adjvex = j; //生成一个边表结点s
s->next = adjlist[i].firstedge; //将结点s插入到i号表的头结点之后
adjlist[i].firstedge = s;
s = new ArcNode;
s->adjvex = i; //生成一个边表结点s
s->next = adjlist[j].firstedge; //将结点s插入到j号表的头结点之后
adjlist[j].firstedge = s;
}
}
/* 前置条件:图已存在
* 输 入:无
* 功 能:销毁图
* 输 出:无
* 后置条件:释放图所占用的存储空间
*/
template <class T>
ALGraph<T>::~ALGraph()
{
for (int i = 0; i < vertexNum; i++)
{
ArcNode* p = adjlist[i].firstedge;
while (p != NULL) //循环删除
{
adjlist[i].firstedge = p->next;
delete p; //释放结点空间
p = adjlist[i].firstedge;
}
}
}
/*
*前置条件:图已存在
*输 入:无
*功 能:输出图中所有顶点及边的数据信息
*输 出:图中所有顶点及边的数据信息
*后置条件:图保持不变
*/
template <class T>
void ALGraph<T>::DispALGraph()
{
int i;
ArcNode* p;
cout << "Graph adjlist:\n";
for (i = 0; i < vertexNum; i++) {
cout << i << " " << adjlist[i].vertex << " "; //输出图中顶点的序号i及值
for (p = adjlist[i].firstedge; p; p = p->next)
cout << p->adjvex << " "; //输出i号顶点的邻接点的序号
cout << endl;
}
}
template <class T>
int ALGraph<T>::Count()
{
int i, n = 0;
for (i = 0; i < vertexNum; i++) visited[i] = 0;
for (i = 0; i < vertexNum; i++) {
if (!visited[i]) {
n++;
BFSTraverse(i); //利用深度优先或广度优先遍历算法均可
}
}
return n;
}
//在下面完成深度优先、广度优先遍历算法
template <class T>
void ALGraph<T>::DFSTraverse(int v)
{
ArcNode* p = NULL;
p = adjlist[v].firstedge;
cout << adjlist[v].vertex << " ";
visited[v] = 1;
while (p)
{
if (visited[p->adjvex] == 0)
{
DFSTraverse(p->adjvex);
visited[p->adjvex] == 1;
}
p = p->next;
}
}
template <class T>
void ALGraph<T>::BFSTraverse(int v)
{
int Q[MaxSize], w, j;
int front=-1, rear=-1;
ArcNode* p = NULL;
p = adjlist[v].firstedge;
cout << adjlist[v].vertex << " ";
Q[++rear] = v;
visited[v] = 1;
while (rear != front)
{
w = Q[++front];
p = adjlist[w].firstedge;
while (p)
{
j = p->adjvex;
if (visited[j] == 0)
{
cout << adjlist[j].vertex<<" ";
Q[++rear] = j;
visited[j] = 1;
}
p = p->next;
}
}
}
int main()
{
string a[] = { "A","B","C","D","E","F","G","H","I","J","K","L","M","N" }; //顶点信息
int i, n, e;
cin >> n >> e; //输入顶点个数和边个数
ALGraph<string> G(a, n, e);
G.DispALGraph();
for (i = 0; i < n; i++)
visited[i] = 0;
cout << "DFS:";
G.DFSTraverse(0);
cout << endl;
for (i = 0; i < n; i++)
visited[i] = 0;
cout << "BFS:";
G.BFSTraverse(0);
// cout<<"\n连通分量个数:";
// cout<<G.Count()<<endl;
return 0;
}
散列表1
题目描述
已知Hash表的表长MaxSize为11,Hash函数为HashFunc(k)=k%11,冲突处理方法为线性探测法,部分代码如下,勿改动。请补充完成成员函数HashSearch,该函数的功能是动态查找k,若查找失败,则插入k,并返回查找失败所需的比较次数,若查找成功,返回查找k所需的比较次数,若表满,则抛出异常“Overflow”
输入
47 7 29 11 16 92 22 8 3 29 0
输出
11 22 -1 47 92 16 3 7 29 8 -1
11 1
22 2
47 1
92 1
16 1
3 4
7 1
29 2
8 2
ASL=1.66667
代码示例
#include <iostream>
using namespace std;
const int MaxSize = 11; //hash表的表长,即教材中的m
class HashList
{
private:
int ht[MaxSize]; // hashtable
public:
int HashFunc(int k); //hash function
HashList(); //consturctor
void Display(); //display
int HashSearch(int k); //dynamic search k
double HashASL(); //search ASL
};
//hash function
int HashList::HashFunc(int k)
{
return k % MaxSize; //hash函数,假设为除余法,余数为MaxSize
}
//constructor:initialize an empty hashlist
HashList::HashList()
{
int i;
for (i = 0; i < MaxSize; i++)
ht[i] = -1; //-1 is empty
}
void HashList::Display()
{
int i;
for (i = 0; i < MaxSize; i++)
cout << ht[i] << " ";
cout << endl;
}
double HashList::HashASL()
{
double ASL = 0;
int i, n = 0;
for (i = 0; i < MaxSize; i++)
if (ht[i] != -1)
{
ASL += HashSearch(ht[i]);
cout << ht[i] << " " << HashSearch(ht[i]) << endl;
n++;
}
// cout<<ASL<<" "<<n<<endl;
return ASL / n;
}
//在下面补充动态查找算法
int HashList::HashSearch(int k)
{
int time = 1;
int hfk = HashFunc(k);
while (ht[hfk]!=-1)//当前位置有元素
{
if (ht[hfk] == k)//找到寻找位置
{
return time;
}
else//找下一个位置
{
time++;
hfk = ++hfk % MaxSize;
}
if (hfk == HashFunc(k))//绕Ht表循环了一次,还是没找到,抛出异常
{
throw"Overflow";
}
}
if (ht[hfk] == -1)//当前位置无元素,执行插入操作
{
ht[hfk] = k;
}
return time;
}
int main()
{
HashList HL;
// HL.Display();
while (1)
{
int k;
cin >> k;
if (!k) break;
try {
HL.HashSearch(k);
}
catch (const char* ms)
{
cout << ms << endl;
}
}
HL.Display();
cout << "ASL=" << HL.HashASL();
return 0;
}
散列表2
题目描述
已知Hash表的表长MaxSize为11,Hash函数为HashFunc(k)=k%11,冲突处理方法为链地址法,部分代码如下,勿改动。请补充完成成员函数HashSearch,该函数的功能是动态查找k,若查找失败,则插入k,并返回查找失败所需的比较次数,若查找成功,返回查找k所需的比较次数。
输入
47 7 29 11 16 92 22 8 3 29 0
输出
Hash address:0,value:22 11
Hash address:1,value:
Hash address:2,value:
Hash address:3,value:3 47
Hash address:4,value:92
Hash address:5,value:16
Hash address:6,value:
Hash address:7,value:29 7
Hash address:8,value:8
Hash address:9,value:
Hash address:10,value:
代码示例
#include<iostream>
using namespace std;
const int MaxSize = 11; //maxsize
struct Node
{
int data;
Node* next;
};
class LinkHash
{
public:
LinkHash(); //initialize an empty list
int HashFunc(int k); //hash function
int HashSearch(int k); //dynamic search k
void Display();
private:
Node* ht[MaxSize]; //ht数组用来保留各个链表的头指针
};
//hash function
int LinkHash::HashFunc(int k)
{
return k % 11; //hash函数,假设为除余法,余数为11
}
//constructor:initialize an empty hashlist
LinkHash::LinkHash()
{
int i;
for (i = 0; i < MaxSize; i++)
ht[i] = nullptr; //empty pointer
}
void LinkHash::Display()
{
int i;
for (i = 0; i < MaxSize; i++)
{
cout << "Hash address:" << i << ",value:";
Node* p;
for (p = ht[i]; p != nullptr; p = p->next)
cout << p->data << " ";
cout << endl;
}
}
//在下面补充实现动态查找算法
int LinkHash::HashSearch(int k)
{
int htn = HashFunc(k);
int time = 1;
Node* q = ht[htn];//工作指针
while (q != NULL)//当工作指针指向位置不为0,后面还有元素
{
if (q->data == k)//找到,插入
{
return time;
}
else//工作指针后移
{
q = q->next;
time++;
}
}
//上面是查找,下面是插入
//先找,实在找不到(工作指针后面没元素了)再插
if (q == NULL)//后面没有元素,没找到,插入
{
Node* p = new Node;
p->data = k;
p->next = ht[htn];
ht[htn]= p;
}
return time;
}
int main()
{
LinkHash LS;
int k;
while (1)
{
cin >> k;
if (!k) break;
try {
LS.HashSearch(k);
// LS.Display();
}
catch (const char* ms)
{
cout << ms << endl;
}
}
LS.Display();
return 0;
}
散列表3
题目描述
已知Hash表的表长MaxSize为11,Hash函数为HashFunc(k)=k%11,冲突处理方法为线性探测法,部分代码如下,勿改动。请补充完成成员函数HashSearch,和函数HashASL,其中函数HashSearch的功能是动态查找k,若查找失败,返回查找失败所需的比较次数,若查找成功,返回查找k所需的比较次数。HashASL的功能是计算等概论查找成功时的ASL值。
输入
47 7 29 11 16 92 22 8 3 29 0
输出
Hash address:0,value:22 11
Hash address:1,value:
Hash address:2,value:
Hash address:3,value:3 47
Hash address:4,value:92
Hash address:5,value:16
Hash address:6,value:
Hash address:7,value:29 7
Hash address:8,value:8
Hash address:9,value:
Hash address:10,value:
ASL=1.33333
代码示例
#include<iostream>
using namespace std;
const int MaxSize = 11; //maxsize
struct Node
{
int data;
Node* next;
};
class LinkHash
{
public:
LinkHash(); //initialize an empty list
int HashFunc(int k); //hash function
int HashSearch(int k); //dynamic search k
void Display();
double HashASL();
private:
Node* ht[MaxSize]; //ht数组用来保留各个链表的头指针
};
//hash function
int LinkHash::HashFunc(int k)
{
return k % 11; //hash函数,假设为除余法,余数为11
}
//constructor:initialize an empty hashlist
LinkHash::LinkHash()
{
int i;
for (i = 0; i < MaxSize; i++)
ht[i] = NULL; //NULL is empty
}
void LinkHash::Display()
{
int i;
for (i = 0; i < MaxSize; i++)
{
cout << "Hash address:" << i << ",value:";
Node* p;
for (p = ht[i]; p; p = p->next)
cout << p->data << " ";
cout << endl;
}
}
int LinkHash::HashSearch(int k)
{
int time = 1;
int htn = HashFunc(k);
Node* q = ht[htn];
while (q != NULL)
{
if (q->data == k)
return time;
else
{
time++;
q = q->next;
}
}
if (q == NULL)
{
Node* p = new Node;
p->data = k;
p->next = ht[htn];
ht[htn] = p;
}
return time;
}
double LinkHash::HashASL()
{
int i,n=0;
double s=0;
for (i = 0; i < MaxSize; i++)
{
Node* p = NULL;
for (p = ht[i]; p; p = p->next)
{
s += HashSearch(p->data);
n++;
}
}
return s / n;
}
int main()
{
LinkHash LS;
int k;
while (1)
{
cin >> k;
if (!k) break;
try {
LS.HashSearch(k);
// LS.Display();
}
catch (const char* ms)
{
cout << ms << endl;
}
}
LS.Display();
cout << "ASL=" << LS.HashASL();
return 0;
}
拓扑排序
题目描述
利用邻接表存储结构实现一个有向图的数据输出,计算各顶点的入度,再输出拓扑排序序列,若拓扑排序失败,输出Failure。已知部分代码如下,勿改动。请完成CountInD,TopSort函数。
Sample Input
6 7
0 1 0 3 1 2 1 5 2 4 3 5 4 5
Sample Output
Graph adjlist:
0 A 3 1
1 B 5 2
2 C 4
3 D 5
4 E 5
5 F
In:0 1 1 1 1 3
TopSort:A B C E D F
参考代码
#include <iostream>
#include <string>
#include<stack>
int Data[1005];
using namespace std;
//栈类
const int StackSize = 100; //10只是示例性的数据,可以根据实际问题具体定义
template <class T> //定义模板类SeqStack
class SeqStack
{
public:
SeqStack(); //构造函数,栈的初始化
~SeqStack(); //析构函数
void Push(T x); //将元素x入栈
T Pop(); //将栈顶元素弹出
T GetTop(); //取栈顶元素(并不删除)
bool Empty(); //判断栈是否为空
bool Full(); //判断栈是否为满
private:
T data[StackSize]; //存放栈元素的数组
int top; //栈顶指针,指示栈顶元素在数组中的下标
};
//初始化空栈
template <class T>
SeqStack<T>::SeqStack()
{
top = -1;
}
//功 能:销毁栈
template <class T>
SeqStack<T>::~SeqStack()
{
}
//功 能:元素x压栈
template <class T>
void SeqStack<T>::Push(T x)
{
if (Full()) throw "Overflow";
top++;
data[top] = x;
}
// 功 能:栈顶元素弹栈
template <class T>
T SeqStack<T>::Pop()
{
T x;
if (Empty()) throw "Downflow";
x = data[top--];
return x;
}
// 功 能:读取当前的栈顶元素
template <class T>
T SeqStack<T>::GetTop()
{
if (Empty())throw"Downflow";
return data[top];
}
//功 能:判断栈是否为空
template <class T>
bool SeqStack<T>::Empty()
{
if (top == -1) return 1;
else return 0;
}
//功 能:判断栈是否为满
template <class T>
bool SeqStack<T>::Full()
{
return top == StackSize - 1;
}
//图
const int MaxSize = 20; // 顶点个数的最大值
int visited[MaxSize]; //访问标志数组(0表示未访问,1表示已访问)
//定义边表结点
struct ArcNode
{
int adjvex; //邻接点的序号
ArcNode* next; //指向下一个边结点的指针
};
//定义顶点表结点
template <class T>
struct VertexNode
{
int in; //各顶点的入度
T vertex; //顶点的名称
ArcNode* firstedge; //指向第一个边表结点的头指针
};
//邻接表类
template <class T>
class ALGraph
{
public:
ALGraph(T a[], int n, int e); //构造函数,初始化一个有n个顶点e条边的图
~ALGraph(); //析构函数,释放邻接表中各边表结点的存储空间
void DispALGraph(); //输出邻接表
void CountInD(); //计算各个顶点的入度,存储在adjlist[i].in中
void DispInD(); //输出各顶点的入度
void TopSort(); //拓扑排序,失败,抛出异常:Failure
private:
VertexNode<T> adjlist[MaxSize]; //存放顶点表的数组
int vertexNum, arcNum; //图的顶点数和边数
};
/*
*前置条件:图不存在
*输 入:无
*功 能:图的初始化
*输 出:无
*后置条件:得到一个无向图
*/
template <class T>
ALGraph<T>::ALGraph(T a[], int n, int e)
{
arcNum = e; //边数
vertexNum = n; //顶点数
int i, j;
for (i = 0; i < vertexNum; i++)
{
adjlist[i].vertex = a[i];
adjlist[i].firstedge = NULL;
}
for (int k = 0; k < arcNum; k++) //依次输入每一条边,并在相应边表中插入结点
{
cin >> i >> j; //输入边所依附的两个顶点的序号
ArcNode* s = new ArcNode;
s->adjvex = j; //生成一个边表结点s
s->next = adjlist[i].firstedge; //将结点s插入到i号表的头结点之后
adjlist[i].firstedge = s;
}
}
/* 前置条件:图已存在
* 输 入:无
* 功 能:销毁图
* 输 出:无
* 后置条件:释放图所占用的存储空间
*/
template <class T>
ALGraph<T>::~ALGraph()
{
for (int i = 0; i < vertexNum; i++)
{
ArcNode* p = adjlist[i].firstedge;
while (p != NULL) //循环删除
{
adjlist[i].firstedge = p->next;
delete p; //释放结点空间
p = adjlist[i].firstedge;
}
}
}
/*
*前置条件:图已存在
*输 入:无
*功 能:输出图中所有顶点及边的数据信息
*输 出:图中所有顶点及边的数据信息
*后置条件:图保持不变
*/
template <class T>
void ALGraph<T>::DispALGraph()
{
int i;
ArcNode* p;
cout << "Graph adjlist:\n";
for (i = 0; i < vertexNum; i++) {
cout << i << " " << adjlist[i].vertex << " "; //输出图中顶点的序号i及值
for (p = adjlist[i].firstedge; p; p = p->next)
cout << p->adjvex << " "; //输出i号顶点的邻接点的序号
cout << endl;
}
}
//计算各个顶点的入度
template <class T>
void ALGraph<T>::CountInD()
{
for (int i = 0; i < vertexNum; i++)
{
adjlist[i].in = 0;
}
for (int i = 0; i < vertexNum; i++)
{
ArcNode* p = adjlist[i].firstedge;
while (p)
{
int t = p->adjvex;
adjlist[t].in += 1;
p = p->next;
}
}
}
//输出各个顶点的入度
template <class T>
void ALGraph<T>::DispInD()
{
int i;
cout << "In:";
for (i = 0; i < vertexNum; i++)
cout << adjlist[i].in << " ";
cout << endl;
}
//topsort
template <class T>
void ALGraph<T>::TopSort()
{
int count = 0;
stack<int> s;
for (int i = 0; i < vertexNum; i++)
{
if (adjlist[i].in == 0) { s.push(i); }
}
while (!s.empty())
{
int t = s.top(); s.pop();
Data[count++] = t;
ArcNode* p = adjlist[t].firstedge;
while (p)
{
int tt = p->adjvex;
if (--adjlist[tt].in == 0)s.push(tt);
p = p->next;
}
}
if (count == vertexNum)
{
cout << "TopSort:";
for (int i = 0; i < count; i++)
cout << adjlist[Data[i]].vertex << " ";
}
else
cout << "Failure";
}
int main()
{
string a[] = { "A","B","C","D","E","F","G","H","I","J","K","L","M","N" }; //顶点信息
int n, e;
cin >> n >> e; //输入顶点个数和边个数
ALGraph<string> G(a, n, e);
G.DispALGraph();
G.CountInD();
G.DispInD();
try {
G.TopSort();
}
catch (const char* ms)
{
cout << ms << endl;
}
//system("pause");
return 0;
}