图oj习题

图的邻接矩阵

深度优先遍历算法(递归)

输出(输出+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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值