精华内容
下载资源
问答
  • 优先排序法
    2018-09-19 12:03:31

    (1)若n较小(如n≤50),可采用直接插入或直接选择排序。
         当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插人,应选直接选择排序为宜。
    (2)若文件初始状态基本有序(指正序),则应选用直接插人、冒泡或随机的快速排序为宜;
    (3)若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。
         快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
         堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。
         若要求排序稳定,则可选用归并排序。先利用直接插入排序求得较长的有序子文件,然后再两两归并之。因为直接插入排序是          稳定的,所以改进后的归并排序仍是稳定的。

    更多相关内容
  • Mckee排序算法(RCM) RCM算法 这是用于反向Cuthill Mckee排序算法(RCM)的Matlab代码。 RCM是一种将具有对称稀疏模式的稀疏矩阵置换为带宽小的带矩阵形式的算法。 实际上,与应用高斯消除的CM命令相比,这通常...
  • 融合聚类算法和缺陷预测的测试用例优先排序方法.pdf
  • 文章目录前言一、拓扑排序规则二、卡恩算法实现1.卡恩算法思想2.代码实现三、dfs+深度优先1.算法思想2.代码实现总结 前言 本篇博客主要记录拓扑排序的实现。包括卡恩算法实现和dfs+深度搜索算法实现。其实这两个...


    前言

    本篇博客主要记录拓扑排序的实现。包括卡恩算法实现和dfs+深度搜索算法实现。其实这两个算法本质分别是广度优先搜索和深度优先搜索。

    一、拓扑排序规则

    首先知道入度和出度的概念,箭头指向本顶点,则本顶点的入度就+1,箭头指出。则出度+1。
    拓扑排序即把出度为0的结点一个一个找出来,看下例子就知道了:
    在这里插入图片描述

    上图中1入度为0,所以1排在前面,此时拓扑排序为{1},将1指出去的箭头都擦去,将下面的继续进行排序:
    在这里插入图片描述
    上图中2出度为0,所以2到拓扑排序中,此时拓扑排序为{1,2},将顶点2和从2指出去的箭头擦去,继续进行找入度为0的顶点:
    在这里插入图片描述
    如上图,此时入度为0的顶点有3,4,5三个顶点,所以这三个顶点谁在前面或者后面都行(这也说明了,拓扑排序结果不具有唯一性)。在这里我们按照3,4,5取,那么拓扑排序为{1,2,3,4,5},最后还剩一个6,入度0,将6放进去,拓扑排序为{1,2,3,4,5,6}。

    拓扑排序需要注意几点:
    (1)AOV网的顶点都是值唯一的,不存在说两个不同的顶点,但是这两个顶点都是A或者说都是1。
    (2)拓扑排序的结果不具有唯一性,因为待排序的顶点中,可能同时有多个顶点入度为0。
    (3)AOV网中不允许存在环,即顺着箭头指向走,不可能再走回到原来的顶点,如下就是有环的(2->3->4->2):
    在这里插入图片描述
    有环的一定会造成死循环,无法进行拓扑排序。

    二、卡恩算法实现

    1.卡恩算法思想

    卡恩算法的思想即将当前的入度为0的顶点取出来,将顶点及和从该顶点出发的箭头擦除,寻找剩下顶点中入度为0的顶点…直到顶点都完成拓扑排序。和上面拓扑排序归则中的思想一样。

    2.代码实现

    拓扑排序的代码中,有多个数组,比如存放原AOV网关系的二维数组vc{{1,2},{1,3},{1,4},{2,4}}就代表一个AOV网:
    (1指向2,我们将2称为1的邻接顶点,1指向3,我们将3称为1的邻接顶点…)
    在这里插入图片描述
    会有一个二维数组neighbor存放每个顶点的邻接顶点,neighbor[1][0]=2表示1的一个邻接顶点是2;neighbor[1][1]=3表示1的一个邻接顶点是3…
    另外会有一个一维数组iv存放每个顶点的入度,iv[1] == 0表示1的此时入度为0,iv[4] == 2表示顶点4的此时入度为2。
    当我们将入度为0 的顶点1拿走时,会用neighbor查询1的邻接点,然后将1的邻接点的入度都-1,再判断这些邻接点的入度-1后是否为0,为0就把顶点拿走…
    由于每个数组之间都有一定的联系,所以导致代码中的数组使用看着有点混乱,但是只要理清楚每个数组什么作用,就比较明了。
    代码:

    //拓扑排序,Kohn算法,有环返回空数组
    vector<int> TuopuSort(vector<vector<int>>& vc, int numV)//numV是顶点的个数
    {
    	vector<int>tar;                   //存放排序后的顶点
    	int numE = vc.size();           //numE是边个数
    	vector<int>iv(numV+1, 0);//iv[i] == j表示顶点i的入度为j
    	vector<vector<int>>neighbor(numV+1);  //neighbor[i][j] == k表示顶点i邻接顶点是k
    
    	for (int i = 0; i < numE; i++)                   //统计每个结点的入度
    	{
    		neighbor[vc[i][0]].push_back(vc[i][1]);//记录顶点vc[i][0]的邻接顶点
    		iv[vc[i][1]]++;                                      //记录顶点的入度
    	}
    
    	queue<int>qu;                      //记录入度为0的顶点
    	for (int i = 1; i < iv.size(); i++)//将入度为0的顶点入到队列中
    	{
    		if (iv[i] == 0)
    		{
    			qu.push(i);
    		}
    	}
    
    	while (!qu.empty())
    	{
    		int t = qu.front(); qu.pop();//取出队列中的一个顶点,队列中的顶点都是入度为0的顶点,注意这里一定要用队列,不能用栈
    		tar.push_back(t);                //将入度为0的顶点加入到tar中
    		for (int i = 0; i < neighbor[t].size(); i++)
    		{
    			if (--iv[neighbor[t][i]] == 0)      //将t的邻接顶点的入度-1,并判断这个邻接顶点入度-1后是否为0,入度为0就入到队列中
    			{
    				if (neighbor[t][i] != 0)//注意邻接点可能是0,0只是标记,不起作用,也不是顶点,所以要加判断
    				{
    					qu.push(neighbor[t][i]);
    				}
    			}
    		}
    	}
    
    	if (tar.size() == numV)          //说明所有顶点都放到tar中了,说明都完成了排序
    		return tar;
    	else
    		return {};
    }
    
    //拓扑排序,两个顶点值不能重复,否则就认为是指同一个顶点,不允许有环,否则排序过后返回空,代表排序失败
    int main()
    {
    	//注意,顶点0不允许使用,顶点最少从1开始,0在拓扑排序中起标识作用
    	//出度和出度都为0的顶点x一开始用{x,0}表示,如下{8,0}表示8是孤立顶点,既没有入度也没有出度
    	vector<vector<int>>vc{ {8,0}, {1,2},{2,7},{7,6},{2,3} ,{2,5},{7,4},{1,3},{3,5}, {5,4} };
    	
    	vector<int>tar = TuopuSort(vc, 8);//传入顶点数
    	for (auto& x : tar)
    	{
    		cout << x << "   ";
    	}
    	cout << endl;
    	return 0;
    }
    

    在这里插入图片描述
    运行结果:
    在这里插入图片描述

    三、dfs+深度优先

    1.算法思想

    主要用dfs和深度优先搜索结合,每次都沿着一条路径一直向下搜索,直到某个顶点的出度为0或被标记已经访问,就停止递归,往回走,在回来的路上记录拓扑排序,即后序遍历。(所以我们得到的拓扑排序是翻着的,反转一下就好了)
    如下图:
    在这里插入图片描述
    从入度为0的顶点深度优先遍历:
    先从1深度优先遍历,再从3深度优先遍历(注意:遍历过的顶点会做标记,不会遍历第二次)
    在这里插入图片描述
    tar中的序列为{6,7,4,2,1,5,3},这个是深度优先遍历的结果,记录的是后序遍历,因为我们是一直向下递归,回退的时候,将结点值一个一个放入到tar中的(见代码实现部分)。反转即为我们要的拓扑排序序列。即拓扑排序序列{3,5,1,2,4,7,6}。

    2.代码实现

    本代码中和卡恩算法一样,需要用vc,neighbor,iv数组,除此之外,本算法还需要数组visit标识结点是否被访问过,visit[i]==true表明i结点被访问过了。
    代码:

    void dfs(vector<int>& tar, vector<bool>& visit, vector<vector<int>>& neighbor, int v)
    {
    	for (int i = 0; i < neighbor[v].size(); i++)//从顶点i开始深度优先遍历
    	{
    		if (!visit[neighbor[v][i]])//说明邻接点没有被访问,从邻接顶点继续向下深度遍历
    		{
    			visit[neighbor[v][i]] = true;
    			dfs(tar, visit, neighbor, neighbor[v][i]);
    		}
    	}
    	if (v != 0)//防止0入拓扑排序(0是标识,方便操作,0不是顶点)
    	{
    		tar.push_back(v);//从后向前记录拓扑序列(得到的是反的拓扑序列)
    	}
    }
    
    
    vector<int> TuopuSort(vector<vector<int>>& vc, int numV)//numV是顶点的个数
    {
    	vector<int>tar;                   //存放排序后的顶点
    	int numE = vc.size();           //numE是边个数
    	vector<int>iv(numV + 1, 0);//iv[i] == j表示顶点i的入度为j
    	vector<vector<int>>neighbor(numV + 1);  //neighbor[i][j] == k表示顶点i邻接顶点是k
    
    	vector<bool> visit(numV + 1, 0);
    
    	for (int i = 0; i < numE; i++)                   //统计每个结点的入度
    	{
    		neighbor[vc[i][0]].push_back(vc[i][1]);//记录顶点vc[i][0]的邻接顶点
    		iv[vc[i][1]]++;                                      //记录顶点的入度
    	}
    
    	for (int i = 1; i <= numV; i++)//遍历顶点
    	{
    		if (iv[i] == 0 && !visit[i])//从入度为0的顶点开始深度优先遍历
    		{
    			visit[i] = true;//遍历过的顶点标志为true
    			dfs(tar, visit, neighbor, i);
    		}
    	}
    	reverse(tar.begin(), tar.end());
    	return tar;
    }
    
    //拓扑排序,两个顶点值不能重复,否则就认为是指同一个顶点,不允许有环,否则排序过后返回空,代表排序失败
    int main()
    {
    	//注意,顶点0不允许使用,顶点最少从1开始
    	//出度和出度都为0的顶点x一开始用{x,0}表示,如下{8,0}表示8是孤立顶点,既没有入度也没有出度
    	vector<vector<int>>vc{ {1,2},{2,4},{2,7},{3,2},{3,4},{3,5},{4,6},{4,7},{5,6},{8,0} };
    
    	vector<int>tar = TuopuSort(vc, 8);//传入顶点数
    	for (auto& x : tar)
    	{
    		cout << x << "   ";
    	}
    	cout << endl;
    	return 0;
    }
    

    在这里插入图片描述

    运行结果:
    在这里插入图片描述

    总结

    卡恩算法本质就是广度优先遍历,比较直接,每次都将产生的入度为0的顶点加到拓扑序列中,直到顶点都被加入进去(除非有环,会导致顶点没有全被加到拓扑序列中,而且也没有入度为0的顶点了,这种情况视为排序失败)。
    dfs+深度优先遍历,主要利用了递归的思想,后序遍历将顶点加入到拓扑序列中,dfs思想保证了每个顶点只被遍历一次。得到的拓扑序列反转即为我们需要的拓扑排序后的结果。这算法没有卡恩算法直接,蒜贩思想也没有卡恩算法的思想更容易理解。

    展开全文
  • 搜索引擎-网络原创文章优先的搜索引擎排序算法研究.pdf
  • 文章目录1. 概述2. 计数排序及实现3. 基数排序(1) 简要介绍(2) ...实际上,快速排序和归并排序已经够用了,它们的平均时间复杂度为 O(nlog⁡n)O(n\log n)O(nlogn) ,任何基于比较的排序算法的时间复杂度都不可能比这


    1. 概述

    我们学过很多排序算法,简单的如冒泡排序、插入排序,麻烦一点的如希尔排序(还不一定写得对)、堆排序,派的上用场的如归并排序快速排序。实际上,快速排序和归并排序已经够用了,它们的平均时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn) ,任何基于比较的排序算法的时间复杂度都不可能比这更优了。

    甚至于,我们不需要自己手写排序算法,C++ STL给我们提供了如下函数,足够满足绝大多数情况下的需求:

    • void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp); :快速排序;
    • void stable_sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp ); :当排序元素相等时,保留原先的顺序;
    • void partial_sort (RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Compare comp); :局部排序,例如有 10 个数字求最小的 5 个数,用 sort() 需要全部排序后再进行输出,而 partial_sort() 可以直接输出前 5 个元素。

    2. 计数排序及实现

    不过有些时候,我们还需要更快的算法。如果要排序的数据满足一些特殊的性质:比如都是不太大的自然数 (<= m) 时,可以使用桶排序/计数排序,将待排序数据作为数组下标。时间复杂度是 O ( n + m ) O(n+m) O(n+m) ,空间复杂度是 O ( m ) O(m) O(m) 。具体代码如下:

    //计数排序
    int cnt[MAXN];
    void countingSort(unsigned A[], int len) {
    	for (int i = 0; i < len; ++i) ++cnt[A[i]];
    	int pos = 0;
    	for (int i = 0; pos < len; ++i) 
    		if (cnt[i])
    			for (int j = 0; j < cnt[i]; ++j)
    				A[pos++] = i;
    }
    

    问题是,当 m m m 稍微大一点,空间就会爆炸。于是我们在这个基础上进行优化,得到了基数排序 Radix Sort


    3. 基数排序

    基数排序是针对自然数(以及其他可以转换为自然数的数据)的排序。它的思想很简单:对数字的每一位分别进行桶/计数排序。其中的基数 radix 就是进制,或者说每一位数字的数据范围。

    (1) 简要介绍

    基数排序分为高位优先低位优先两种。其中,高位优先是指先按照高位的数字进行计数排序,此时能够直接区分所有数的大小,然后递归对每个桶中的数据的次高位进行基数排序。总的来说,高位优先基数排序性能不如低位优先,因此不太常用。

    下面我们以 10 为基数进行低位优先的基数排序。有这么几个数据:14579, 54929, 41488, 13692, 2048 。首先按照最低位进行计数排序:
    在这里插入图片描述
    第一趟计数排序结束后,所有的数已经按照最低一位排好序。然后按照次低位进行排序:
    在这里插入图片描述
    此时,所有数的末两位已经排好序。这个过程进行下去,直至遍历完所有位,完成整个数据的排序。总的来说,低位优先基数排序从低位到高位,依次进行计数排序(或者其他稳定的排序)

    (2) 具体实现:10进制低位优先基数排序

    10 10 10 为基数的,一般的实现会从小到大准备 10 10 10 个链队列,然后将所有数据按照最低位分配 10 10 10 个链队列中,再依次收集起来;然后按照次低位进行分配,再进行收集……直到完成排序。不过这样太麻烦,这里给出使用数组 10 10 10 进制低位优先基数排序:

    • 要排序的正整数数组 arr[] 大小为 N N N ,我们需要先创建一个大小为 10 × N 10\times N 10×N 的二维数组 idx[10][N] ,用来进行数据的分配和收集;
    • 之后,我们找到 arr[] 中最大的数,计算出它的位数为 k k k ,这代表着我们只用进行 k k k 次计数排序;如果有负整数,就比较绝对值的大小;这一步不是很重要,可以省略;
    • 然后我们根据 arr[] 中每个数的最低位进行排序,再根据十位进行排序……直到对第 k k k 位进行排序。此时,排在我们创建的数组 idx[][] 中的数据已经完成排序,只需要输出即可。

    这样可能还是有点看不懂,现在举个例子,要排序的数组为 arr[] = {121, 5, 4564, 9320, 6, 2, 1, 1234}

    • 首先创建出一个二维数组 idx[][] ,大小为 10 × 8 10 \times 8 10×8
    • 之后,找到数据中的最大数,这里是 9321 9321 9321 ,得到它的位数 4 4 4 位;
    • 然后根据数据的个位进行排序,第 0 0 0 个数 121 121 121 的个位是 1 1 1 ,所以放在 idx[1][0] 处;第 1 1 1 个数 5 5 5 的个位是 5 5 5 ,所以将它放在 idx[5][1] 上……依次类推;
    • 将数据都根据个位排入数组后,按照顺序用待排数组将它们收集起来,从第 0 0 0 行开始读到第 9 9 9 行,从左读到右。得到按个位从小到大排好的数组 arr[] = {9320, 121, 1, 2, 4564, 1234, 5, 6}
    • 当我们把数据读出来后,记得要把创建的数组 idx[10][N] 清零,供下次使用;
    • 接下来对十位进行排序,用刚刚读出来的新数组,第 0 0 0 个数是 9320 9320 9320 ,它的十位是 2 2 2 ,就把它放在 idx[2][0] 上,这一过程基本一致……要注意第 2 2 2 个数是 1 1 1 ,没有十位,我们把它的十位当成 0 0 0 ,排到 idx[0][2] 就可以了;
    • 再按之前的顺序读取数据,得到这样的数组 {1, 2, 5, 6, 9320, 121, 1234, 4564} ,清零 idx[10][N]
    • 然后按照这一过程,对百位和千位进行相同的排序,就可以得到最后排序好的数组了。

    为了验证我们代码的效率和准确性,使用洛谷 P1177 【模板】快速排序进行评判,这道题的数据可以卡死很多写得差的快速排序:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 10;
    int arr[maxn], idx[10][maxn], n, mx = -1; 
    
    int main() { 
    	scanf("%d", &n); 
    	for (int i = 0; i < n; ++i) {
    		scanf("%d", &arr[i]);
    		mx = max(mx, arr[i]);
    	}
    	int digits = 0, ten = 1;
    	do { ++digits; mx /= 10; } while (mx); 
    	for (int i = 0; i < digits; ++i) { //进行len次计数排序 
    		for (int j = 0; j < n; ++j)    //将每个数按照给出的j的顺序,排到创建的数组中
    			idx[(arr[j] / ten) % 10][j] = arr[j]; 
    		//按照顺序读取排好的数组
    		int len = 0;
    		for (int j = 0; j <= 9; ++j)
    			for (int k = 0; k < n; ++k)
    				if (idx[j][k])
    					arr[len++] = idx[j][k];
    		memset(idx, 0, sizeof(idx));   //清空idx
    		ten *= 10;					   //ten*10,下次循环排序更高一位 
    	}
    	for (int i = 0; i < n; ++i) printf(" %d" + !i, arr[i]);
        return 0;
    }
    

    运行效果如下:
    在这里插入图片描述


    (3) 优化:65536进制低位优先基数排序

    优化之路永无止境。以 65536 65536 65536 为基数,此时对 32 32 32 位的整数,只需要进行两次计数排序——先对低 16 16 16 位再对高 16 16 16 位。具体排序代码如下:

    inline void radixSort(unsigned A[], int len) {
    	unsigned *B = new unsigned[len];
    	int r = 65535; //基数为65535
    	int L[r + 1] = {0}, H[r + 1] = {0}; //分别对低16位和高16位计数
    	for (int i = 0; i < len; ++i) 
    		++L[A[i] & r], ++H[(A[i] >> 16) & r); //计数排序
    	for (int i = 1; i <= r; ++i) 
    		L[i] += L[i - 1], H[i] += H[i - 1]; //求前缀和
    	for (int i = len - 1; i >= 0; --i)
    		B[--L[A[i] & r]] = A[i];	//对低位进行计数排序
    	for (int i = len - 1; i >= 0; --i)
    		A[--H[(B[i] >> 16) & r]] = B[i];	//对高位进行计数排序
    	delete [] B;
    }
    

    这里解释一下为什么要求前缀和。例如数列 3 , 1 , 4 , 3 3, 1, 4, 3 3,1,4,3 进行 10 10 10 进制计数后得到的数组 L 应该如下:
    在这里插入图片描述
    求前缀和之后,L 数组变为:
    在这里插入图片描述

    所以求前缀和后的 L[i] ,表示的是低 16 16 16<= i 的所有数排序后最后一个数的位置 +1 ,可以在排序时确定位置。

    提交到洛谷上,结果如下,效率几乎翻倍:
    在这里插入图片描述


    (3) 毒瘤实现:256进制低位优先基数排序

    对于 32 32 32 位整数而言,选择 65536 65536 65536 作为基数几乎是最优的选择:速度快、容易写。但是也有题目如P4604 [WC2017]挑战一样卡常数,需要以 256 256 256 作为基数。代码如下,和 65536 65536 65536 的区别不大:

    inline void radix_sort(unsigned A[], int len) {
    	unsigned *B = new unsigned[len];
    	int r = 255;
    	int L1[r + 1] = {0}, L2[r + 1] = {0}, H1[r + 1] = {0}, H2[r + 1] = {0}; //H2H1L2L1
    	for (int i = 0; i < len; ++i) {
    		++L1[A[i] & r];
    		++L2[(A[i] >> 8) & r];
    		++H1[(A[i] >> 16) & r];
    		++H2[(A[i] >> 24) & r];
    	}
    	for (int i = 1; i <= r; ++i) {
    		L1[i] += L1[i - 1];
    		L2[i] += L2[i - 1];
    		H1[i] += H1[i - 1];
    		H2[i] += H2[i - 1];
    	}
    	for (int i = len - 1; i >= 0; --i) 
    		B[--L1[A[i] & r]] = A[i];
    	for (int i = len - 1; i >= 0; --i)
    		A[--L2[(A[i] >> 8) & r]] = B[i];
    	for (int i = len - 1; i >= 0; --i)
    		B[--H1[(A[i] >> 16) & r]] = A[i];
    	for (int i = len - 1; i >= 0; --i)
    		A[--H2[(A[i] >> 24) & r]] = B[i];
    	delete [] B;
    }
    

    利用洛谷的快速排序模板题进行测试,和 65536 65536 65536 没有太大区别:
    在这里插入图片描述


    上述代码都是对无符号整数进行的排序。如果要排序有符号整数,只需要先把所有数加上 0x80000000 转换为无符号整数,排序结束后再减去即可。另外,还可以用基数排序对浮点数排序。

    展开全文
  • 各种排序算法汇总,包括插入排序、基数排序等
  • 4、排序函数:对就绪状态的进程按照优先排序优先权相同时进入等待队列时间早的进程在前。注意考虑到达时间 5、调度函数:每次从等待队列队首调度优先权最高的进程执行,状态变化。并在执行一个时间单位后优先权...
  • DFS.py 深度优先遍历获取基础路经,path_dfs_all.txt 是结果;path_dfs.txt 是部分结果;path_threshold.txt是加了限制后的结果 model.py 获取实体路经三元组的特征值,train_data.txt是全量的训练数据,第一位表示...
  • 通过深度优先算法进行拓扑排序(Java) package graph; //拓扑排序用深度优先算法实现 import java.io.IOException; import java.util.Scanner; import java.util.Stack; public class Topological { private ...

    通过深度优先算法进行拓扑排序(Java)

    package graph;
    //拓扑排序用深度优先算法实现
    import java.io.IOException;
    import java.util.Scanner;
    import java.util.Stack;
    public class Topological 
    {
    
    	private class ENode 
    	{
    		int ivex; // 该边所指向的顶点的位置
    		ENode nextEdge; // 指向下一条弧的指针
    	}
    
    	// 邻接表中表的顶点
    	private class VNode 
    	{
    
    		int color;// 顶点颜色;
    		int d;// 初始时间戳;
    		int f;// 结束时间戳;
    		char data; // 顶点信息
    		ENode firstEdge; // 指向第一条依附该顶点的弧
    		VNode pre;
    	};
    
    	int time;
    	private VNode[] mVexs; // 顶点数组
    
    	/*
    	 * 创建图(自己输入数据)
    	 */
    	public Topological() 
    	{
    
    		// 输入"顶点数"和"边数"
    		System.out.printf("input vertex number: ");
    		int vlen = readInt();
    		System.out.printf("input edge number: ");
    		int elen = readInt();
    		if (vlen < 1 || elen < 1 || (elen > (vlen * (vlen - 1)))) 
    		{
    			System.out.printf("input error: invalid parameters!\n");
    			return;
    		}
    
    		// 初始化"顶点"
    		mVexs = new VNode[vlen];
    		for (int i = 0; i < mVexs.length; i++) 
    		{
    			System.out.printf("vertex(%d): ", i);
    			mVexs[i] = new VNode();
    			mVexs[i].data = readChar();
    			mVexs[i].firstEdge = null;
    		}
    
    		// 初始化"边"
    		// mMatrix = new int[vlen][vlen];
    		for (int i = 0; i < elen; i++) 
    		{
    			// 读取边的起始顶点和结束顶点
    			System.out.printf("edge(%d):", i);
    			char c1 = readChar();
    			char c2 = readChar();
    			int p1 = getPosition(c1);
    			int p2 = getPosition(c2);
    			// 初始化node1
    			ENode node1 = new ENode();
    			node1.ivex = p2;
    			// 将node1链接到"p1所在链表的末尾"
    			if (mVexs[p1].firstEdge == null)
    				mVexs[p1].firstEdge = node1;
    			else
    				linkLast(mVexs[p1].firstEdge, node1);
    		}
    	}
    
    	/*
    	 * 创建图(输入有向图矩阵)
    	 * 参数说明: vexs -- 顶点数组 edges -- 边数组
    	 */
    	public Topological(char[] vexs, char[][] edges) 
    	{
    
    		// 初始化"顶点数"和"边数"
    		int vlen = vexs.length;
    		int elen = edges.length;
    
    		// 初始化"顶点"
    		mVexs = new VNode[vlen];
    		for (int i = 0; i < mVexs.length; i++)
    		{
    			mVexs[i] = new VNode();
    			mVexs[i].data = vexs[i];
    			mVexs[i].firstEdge = null;
    		}
    
    		// 初始化"边"
    		for (int i = 0; i < elen; i++)
    		{
    			// 读取边的起始顶点和结束顶点
    			char c1 = edges[i][0];
    			char c2 = edges[i][1];
    			// 读取边的起始顶点和结束顶点
    			int p1 = getPosition(edges[i][0]);
    			int p2 = getPosition(edges[i][1]);
    
    			// 初始化node1
    			ENode node1 = new ENode();
    			node1.ivex = p2;
    			// 将node1链接到"p1所在链表的末尾"
    			if (mVexs[p1].firstEdge == null)
    				mVexs[p1].firstEdge = node1;
    			else
    				linkLast(mVexs[p1].firstEdge, node1);
    		}
    	}
    
    	/*
    	 * 将node节点链接到list的最后
    	 */
    	private void linkLast(ENode list, ENode node)
    	{
    		ENode p = list;
    
    		while (p.nextEdge != null)
    			p = p.nextEdge;
    		p.nextEdge = node;
    	}
    
    	/*
    	 * 返回ch位置
    	 */
    	private int getPosition(char ch)
    	{
    		for (int i = 0; i < mVexs.length; i++)
    			if (mVexs[i].data == ch)
    				return i;
    		return -1;
    	}
    
    	/*
    	 * 读取一个输入字符
    	 */
    	private char readChar() 
    	{
    		char ch = '0';
    
    		do {
    			try 
    			{
    				ch = (char) System.in.read();
    			} catch (IOException e) 
    			{
    				e.printStackTrace();
    			}
    		} while (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')));
    
    		return ch;
    	}
    
    	/*
    	 * 读取一个输入字符
    	 */
    	private int readInt() 
    	{
    		Scanner scanner = new Scanner(System.in);
    		return scanner.nextInt();
    	}
    
    	/* 深度优先搜索遍历图的递归实现*/
    	Stack<Integer> stack = new Stack<Integer>();//辅助栈;
    	public void DFS_visit(int i, boolean[] visited) 
    	{	
    		ENode node;
    		// time= time+1;
    		mVexs[i].d = ++time;
    		mVexs[i].color = 0;// 1表示该节点颜色为灰色
    		visited[i] = true;
    		System.out.printf("%c(%d) ", mVexs[i].data,mVexs[i].d);//颜色
    		node = mVexs[i].firstEdge;
    		while (node != null) 
    		{
    			if (mVexs[node.ivex].color == -1)
    			{
    				// System.out.println("("+i+","+node.ivex+")---树边");
    				DFS_visit(node.ivex, visited);
    			} else if (mVexs[node.ivex].color == 0)
    			{
    				System.out.println("(" + i + "," + node.ivex + ")---后向边,有环图,无拓扑排序");
    
    			}
    //            else
    //            {
    //            	if(mVexs[i].color < mVexs[node.ivex].d)
    //            		System.out.println("("+i+","+node.ivex+")---前向边");
    //            	else if(mVexs[i].color > mVexs[node.ivex].d)
    //            		System.out.println("("+i+","+node.ivex+")---横跨边");
    //            }     
    			node = node.nextEdge;
    		}
    		mVexs[i].color = 1;
    		// time=time+1;
    		mVexs[i].f = ++time;
    		stack.push(i);
    		System.out.printf("%c(%d) ", mVexs[i].data,mVexs[i].f);
    		
    	}
    
    	/*
    	 * 深度优先搜索遍历图
    	 */
    	public void DFS()
    	{
    		time = 0;
    		boolean[] visited = new boolean[mVexs.length]; // 顶点访问标记
    
    		// 初始化所有顶点都没有被访问
    		for (int i = 0; i < mVexs.length; i++) 
    		{
    			mVexs[i].color = -1;// 初始化所有顶点都为白色
    			mVexs[i].pre = null;
    			visited[i] = false;
    		}
    		System.out.printf("DFS: ");
    		for (int j = 0; j < mVexs.length; j++) 
    		{
    			if (!visited[j])
    				DFS_visit(j, visited);
    		}
    		System.out.print("\n拓扑排序为:");
    		for (int i = 0; i < mVexs.length; i++) 
    		{
    			System.out.print(mVexs[stack.pop()].data+" ");
    		}
    		
    		
    	}
    
    	/*
    	 * 打印矩阵队列图
    	 */
    	public void print() {
    		System.out.printf("List Graph:\n");
    		for (int i = 0; i < mVexs.length; i++)
    		{
    			System.out.printf("%d(%c): ", i, mVexs[i].data);
    			ENode node = mVexs[i].firstEdge;
    			while (node != null) 
    			{
    				System.out.printf("%d(%c) ", node.ivex, mVexs[node.ivex].data);
    				node = node.nextEdge;
    			}
    			System.out.printf("\n");
    		}
    	}
    
    	public static void main(String[] args) {
    		char[] vexs = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
    		char[][] edges = new char[][] { 
    			{ 'B', 'A' }, 
    			{ 'B', 'D' }, 
    			{ 'A', 'G' }, 
    			{ 'C', 'G' }, 
    			{ 'D', 'F' },
    			{ 'C', 'F' },
    			{ 'D', 'E' },};
    		Topological pG;
    
    		// 自定义"图"(输入矩阵队列)
    		// pG = new ListDG();
    		// 采用已有的"图"
    		pG = new Topological(vexs, edges);
    		pG.print(); // 打印图
    		pG.DFS(); // 深度优先遍
    	}
    
    }
    
    
    展开全文
  • 现有的搜索引擎排序算法大多根据网页之间的链接关系进行排序,没有考虑原创和转载文章之间的优先次序。该文提出一种适用于专业搜索引擎的新型排序算法,在排序时优先考虑原创文章,使原创文章的搜索排名得以提高,有...
  • 基于离散粒子群算法的测试用例优先排序.pdf
  • 基于改进粒子群算法的测试用例优先排序.pdf
  • LSD:低位优先的字符串排序,核心思想就是对字符串的每个字符做一次键索引排序 #include <iostream> #include <utility> #include <vector> #include <string> using namespace std; int...
  • C++中优先队列和sort自定义排序算法对比!! 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本...
  • NULL 博文链接:https://robblog.iteye.com/blog/566114
  • 当面临巨大数据量的排序的时候,还是优先选择合并排序算法和快速排序算法。而选择排序算法、冒泡排序算法和插入排序算法不太适用于大数据排序。 现在有 1 亿的数据,请选择合适的排序算法与数据结构,在有限的时间内...
  • 为减少深度Q网络(DQN)算法的训练时间,采用结合优先经验回放机制与竞争网络结构的DQN方法,针对Open AI Gym平台cart pole和mountain car两个经典控制问题进行研究,其中经验回放采用基于排序的机制,而竞争结构中...
  • 针对这个问题,文章将依赖关系重新到优先级技术,提出一种基于依赖结构的测试用例优先级技术,首先将依赖关系转化为量化指标依赖深度,然后逐步指标为权重函数,使用扩展的深度优先搜索算法进行测试用例排序。...
  • 一、快速排序 三、图 四、广度优先搜索算法
  • 排序算法08:优先队列与堆排序

    千次阅读 2017-05-03 23:56:38
    这也是《算法》第四版上讲解堆排序的大致章节结构。另外,本文所有的图都来自于此书。优先队列  普通队列是一种先进先出的数据结构,先放进队列的元素取值时优先被取出来。而优先队列是一种具有最高优先级元素先出...
  • 基数排序-最低位优先法

    千次阅读 2020-11-04 21:55:31
    基数排序-最低位优先法 算法思维 基数排序是一种非比较型的排序,其原理是把数字按位数分割,然后对每一位进行分配和收集 最低位优先法就是从数字的最低为开始,依次分配和收集 最低位优先法相较于最高位优先法,...
  • 论文研究-云南优势产业发展优先排序.pdf, 针对云南省各优势产业的发展特点,由专家填写“对目标影响因素的成对比较阵”,用“多层次权重分析方法”及“聚类分析”综合...
  • LLF算法根据实时任务的松弛度来确定任务的优先权,即任务的松弛度越低,其优先权越高。在实现该算法时,要求系统中有一个按松弛度排序的实时任务就绪队列。该算法通常采用抢占方式,当一个任务的最低松弛度为 0 时,...
  • 十大排序算法:快速排序算法

    千次阅读 2021-04-09 19:57:20
    一、快速排序算法思想或步骤 分解: 数组A[p…r]被划分为两个子数组A[p…q-1]和A[q+1…r],使得A[q]为大小居中的数,左侧A[p…q-1]中的每个元素都小于等于它,而右边A[q+1…r]每个元素都大于等于它。 解决: 通过...
  • 1.需求分析 ①.问题描述 给出一组数据,按照最低位优先的方法完成基数排序。多关键码排序按照从最主位关键码到最次位或从最次位到最主位关键码的顺序逐次排序
  • 排序算法详细讲解(超酷)

    千次阅读 多人点赞 2022-03-28 08:50:56
    排序算法作为数据结构中重要的部分,是必须要掌握的知识之一。 目录 前言 一、插入类排序 1.直接插入排序 2.折半插入排序 3.希尔排序 二、交换类排序 1.冒泡排序(相邻比序) 2.快速排序 三、选择类...
  • 算法 —— 排序 —— 优先队列

    千次阅读 2018-06-02 19:40:28
    优先队列 二叉堆 优先队列 【Priority Queue】 首先声明一下,优先队列是基于堆的完全二叉树,它和队列的概念无关。(它并不是队列,而是树) 并且,优先队列最重要的操作就是: 删除最大元素和插入元素,...
  • 基于比较的七种常见排序算法

    千次阅读 多人点赞 2021-10-21 23:32:56
    本文主要介绍基于比较的七种常见排序算法,分别为:选择排序法,插入排序法,希尔排序法,冒泡排序法,堆排序法,归并排序法,快速排序法。 基于比较的排序算法是指对于元素的排序必须是建立在元素之间是可以比较的...
  • 短作业优先调度算法

    2019-05-12 18:43:40
    模拟实现短作业调度算法,具体如下: 1、 设置作业体:作业名,作业的到达时间,服务时间,作业间的链接指针; 2、 进程初始化:由用户输入作业名、作业的到达时间和服务时间进行初始化; 3、 显示函数: 显示当前...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 159,887
精华内容 63,954
关键字:

优先排序法