53.String sort 字符串排序的几种方法

53.String sort 字符串排序的几种方法
53.String sort 字符串排序的几种方法

String sort的几种方法

简介

在之前的一些排序算法中,主要是对一些数值的类型比较的比较多一点。而对于字符串类型来说,它有一些特殊的性质。如果按照传统的排序方法,对于字符串的比较性能其实还取决于字符串的长度以及相似程度。实际上,对于一些字符集的取值在一个比较小的范围内的情况,我们可以有一些比较高效率的算法。这里针对这些特殊的情况进行讨论。

假设给定的排序集合里元素,也就是每个字符都是在一个比较有限的范围里,比如说256个字符范围内。那么,我们可以利用这个特性做一些高效的处理。联想到之前讨论过的counting sort和radix sort方法。这里就是利用了这个特性。

Key-Indexed counting

在之前讨论couting sort的文章里,曾经针对需要排序的元素为数字的情况进行过讨论。counting sort成立的一个前提是它里面所有的元素取值是在一个固定的范围内。假设这个数组里元素能取的最大值是k,那么每次我们要排序的时候只需要声明一个长度为k的数组a。每次碰到一个元素i就将a[i]对应的值加1。这样就统计出来了所有从小到大的元素的值的分布。剩下的就只是从小到达把这些值重新排列输出就可以了。

当然,在一些数字有一定长度而且它们的长度都一样的情况下。我们可以利用从高到低或者从低到高位逐位排序的方式来对数组进行排序。这就是radix sort的基本思路。它本质上就是在每一位的排序上都使用了couting sort。

借鉴前面对于数字的排序,我们对于字符串数组的排序也可以采用类似的方式:

Java代码

1.int[] count = new int[R + 1];

2.//计算每个字符出现的频率

3.for(int i = 0; i < n; i++)

4. count[a[i].charAt(d) + 1]++;

5.//将每个字符出现的频率转换为所在的索引

6.for(int r = 0; r < R; r++)

7. count[r + 1] += count[r];

8.//将字符分布到具体的数组位置

9.for(int i = 0; i < n; i++)

10. aux[count[a[i].charAt(d)]++] = a[i];

11.//将结果拷贝回数组

12.for(int i = 0; i < n; i++)

13. a[i] = aux[i];

上述代码里的R表示当前字符的取值范围。在R值不大的时候它的效率还是相当可观的。在这个计数排序的基础上,我们可以得到一些不同的排序算法。

LSD sort

一种最典型的方法就是从最低位向最高位的方式依次排序,这种和前面的radix sort的思路基本上完全一样。不过在前面的基础上针对字符的情况稍微做一点修改。详细的代码实现如下:

Java代码

1.public class LSD {

2.public static void sort(String[] a, int w) {

3.int n = a.length;

4.int R = 256;

5. String[] aux = new String[n];

6.for(int d = w - 1; d >= 0; d--) {

7.int[] count = new int[R + 1];

8.for(int i = 0; i < n; i++)

9. count[a[i].charAt(d) + 1]++;

10.

11.for(int r = 0; r < R; r++)

12. count[r + 1] += count[r];

13.

14.for(int i = 0; i < n; i++)

15. aux[count[a[i].charAt(d)]++] = a[i];

16.

17.for(int i = 0; i < n; i++)

18. a[i] = aux[i];

19. }

20. }

21.}

对于等长的字符串,而且里面字符的取值在一个比较小范围内时,这种LSD排序的方式比较理想。那么,如果我们把条件稍微放宽一点,如果字符串的长度其实不是等长的呢?有没有办法利用前面的计数排序呢?

MSD

和前面LSD不一样的就是,我们可以采用从最高位到最低位排序的方式来排序,同时,它可以处理数组长度不一致的情况。一般来说,当数组长度一致的时候,我们定义一个对应的数组来映射它所在的索引,如果不一致的时候就会出现当访问到某个位置的时候,其中某个字符串已经超出访问范围了。这时候该怎么办呢?

对于超出字符串访问范围的,我们可以定义一个charAt(i)的方法,超过范围的元素返回索引值-1。这样所有超出原来范围的数组都可以集中统计在-1的这个位置上。在详细映射实现的时候,我们可以将数组的长度加长一位。所有映射到索引位置的元素加一,这样-1位置的元素就相当于新数组里索引为0的位置。这样可以得到一个实现:

Java代码

1.public class MSD {

2.private static int R = 256;

3.private static final int M = 15;

4.private static String[] aux;

5.

6.private static int charAt(String s, int d) {

7.if(d < s.length()) return s.charAt(d);

8.else return -1;

9. }

10.

11.public static void sort(String[] a) {

12.int n = a.length;

13. aux = new String[n];

14. sort(a, 0, n - 1, 0);

15. }

16.

17.private static void sort(String[] a, int lo, int hi, int d) {

18.if(hi <= lo + M) {

19. Insertion.sort(a, lo, hi, d);

20.return;

21. }

22.int[] count = new int[R + 2];

23.for(int i = lo; i <= hi; i++)

24. count[charAt(a[i], d) + 2]++;

25.

26.for(int r = 0; r < R + 1; r++)

27. count[r + 1] += count[r];

28.

29.for(int i = lo; i <= hi; i++)

30. aux[count[charAt(a[i], d) + 1]++] = a[i];

31.

32.for(int i = lo; i <= hi; i++)

33. a[i] = aux[i - lo];

34.

35.for(int r = 0; r < R; r++)

36. sort(a, lo + count[r], lo + count[r + 1] - 1, d + 1);

37. }

38.}

这种实现显得稍微复杂一点,不过在一定程度上当超出长度的元素比较少的时候,应该可以有更进一步的优化空间。

Three-way string quicksort

除了上述两种排序的方式,还有一种比较有意思的排序方法。它借鉴了快速排序的思路。就是每次取一个字符串中某个位置的字符作为节点,将字符串数组按照这个节点划分成小于等于以及大于它的三个部分。然后类似于快速排序的方法,对于大于以及小于它的部分递归的进行排序。而对于等于这个节点的部分,如果有多个的话则进一步按照下一个位置的字符进行递归排序。

在排序的过程里,考虑到有相同元素的情况,它的实现和单纯的快速排序划分还稍微有点不一样。详细的实现代码如下:

Java代码

1.public class Quick3string {

2.private static int charAt(String s, int d) {

3.if(d < s.length())

4.return s.charAt(d);

5.else return -1;

6. }

7.

8.public static void sort(String[] a) {

9. sort(a, 0, a.length - 1, 0);

10. }

11.

12.private static void sort(String[] a, int lo, int hi, int d) {

13.if(hi <= lo) return;

14.int lt = lo, gt = hi;

15.int v = charAt(a[lo], d);

16.int i = lo + 1;

17.while(i <= gt) {

18.int t = charAt(a[i], d);

19.if(t < v) exch(a, lt++, i++);

20.else if(t > v) exch(a, i, gt--);

21.else i++;

22. }

23.

24. sort(a, lo, lt - 1, d);

25.if(v >= 0) sort(a, lt, gt, d + 1);

26. sort(a, gt + 1, hi, d);

27. }

28.}

由于exch方法仅仅是交换两个元素的位置,实现比较简单,这里就忽略了。这种方法对于有大量重复元素的字符串数组有比较好的排序效果。

总结

虽说是对字符串数组进行排序。在传统的排序比较方法里,我们需要针对数组里每个元素比较的时候要从头到位的比对。有时候对于元素取值范围比较固定的情况可以有一定的优化空间。这里就利用了couting sort 和radix sort的思路。而在有大量相同前缀部分的字符串数组排序方法里,我们可以考虑使用类似于快速排序的方法,每次取一个位对数组进行划分,这样逐步递归的实现排序。这里面的详细实现细节值得反复推敲。

参考材料

algorithms

排 列 组 合 公 式 及 排 列 组 合 算 法

排列组合n选m,组合算法——0-1转换算法(巧妙算法)C++实现 知识储备 排列的定义:从n个不同元素中,任取m(m≤n,m与n均为自然数,下同)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 A(n,m)表示计算公式: 注意:m中取n个数,按照一定顺序排列出来,排列是有顺序的,就算已经出现过一次的几个数。只要顺序不同,就能得出一个排列的组合,例如1,2,3和1,3,2是两个组合。 组合的定义:从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示。 计算公式: 注意:m中取n个数,将他们组合在一起,并且顺序不用管,1,2,3和1,3,2其实是一个组合。只要组合里面数不同即可 组合算法 本算法的思路是开两个数组,一个index[n]数组,其下标0~n-1表示1到n个数,1代表的数被选中,为0则没选中。value[n]数组表示组合

的数值,作为输出之用。 ? 首先初始化,将index数组前m个元素置1,表示第一个组合为前m 个数,后面的置为0。? 然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为?“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。一起得到下一个组合(是一起得出,是一起得出,是一起得出)重复1、2步骤,当第一个“1”移动到数组的n-m的位置,即m个“1”全部移动到最右端时;即直到无法找到”10”组合,就得到了最后一个组合。 组合的个数为: 例如求5中选3的组合: 1 1 1 0 0 --1,2,3? 1 1 0 1 0 --1,2,4? 1 0 1 1 0 --1,3,4? 0 1 1 1 0 --2,3,4? 1 1 0 0 1 --1,2,5? 1 0 1 0 1 --1,3,5? 0 1 1 0 1 --2,3,5? 1 0 0 1 1 --1,4,5? 0 1 0 1 1 --2,4,5? 0 0 1 1 1 --3,4,5 代码如下:

排序练习题

【程序改错】 功能:在一个已按升序排列的数组中插入一个数,插入后,数组元素仍按升序排列。 #define N 11 main() { int i,j,t,number,a[N]={1,2,4,6,8,9,12,15,149,156}; printf("please enter an integer to insert in the array:\n"); /**********FOUND**********/ scanf("%d",&number) printf("The original array:\n"); for(i=0;i=0;i) if(number<=a[i]) /**********FOUND**********/ a[i]=a[i1]; else { a[i+1]=number; /**********FOUND**********/ exit; } if(number #include #include main() { FILE *fp; char t,str[100],str1[100]; int n,i,j; if((fp=fopen("test.txt","w"))==NULL) {

昵称排序用什么字符 (什么字符排在最前)

ASCII 1 = ASCII 2 = ASCII 3 = ASCII 4 = ASCII 5 = ASCII 6 = ASCII 7 = ASCII 8 = ASCII 9 = ASCII 10 = ASCII 11 = ASCII 12 = ASCII 13 = ASCII 14 = ASCII 15 = ASCII 16 = ASCII 17 = ASCII 18 = ASCII 19 = ASCII 20 = ASCII 21 =

ASCII 23 = ASCII 24 = ASCII 25 = ASCII 26 = ASCII 27 = ASCII 28 = ASCII 29 = ASCII 30 = - ASCII 31 = ASCII 32 = ASCII 33 = ! ASCII 34 = " ASCII 35 = # ASCII 36 = $ ASCII 37 = % ASCII 38 = & ASCII 39 = ' ASCII 40 = ( ASCII 41 = ) ASCII 42 = *

ASCII 44 = , ASCII 45 = - ASCII 46 = . ASCII 47 = / ASCII 48 = 0 ASCII 49 = 1 ASCII 50 = 2 ASCII 51 = 3 ASCII 52 = 4 ASCII 53 = 5 ASCII 54 = 6 ASCII 55 = 7 ASCII 56 = 8 ASCII 57 = 9 ASCII 58 = : ASCII 59 = ; ASCII 60 = < ASCII 61 = = ASCII 62 = > ASCII 63 = ?

各种排序算法比较

排序算法 一、插入排序(Insertion Sort) 1. 基本思想: 每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。 2. 排序过程: 【示例】: [初始关键字] [49] 38 65 97 76 13 27 49 J=2(38) [38 49] 65 97 76 13 27 49 J=3(65) [38 49 65] 97 76 13 27 49 J=4(97) [38 49 65 97] 76 13 27 49 J=5(76) [38 49 65 76 97] 13 27 49 J=6(13) [13 38 49 65 76 97] 27 49 J=7(27) [13 27 38 49 65 76 97] 49 J=8(49) [13 27 38 49 49 65 76 97] Procedure InsertSort(Var R : FileType); //对R[1..N]按递增序进行插入排序, R[0]是监视哨// Begin for I := 2 To N Do //依次插入R[2],...,R[n]// begin R[0] := R[I]; J := I - 1; While R[0] < R[J] Do //查找R[I]的插入位置// begin R[J+1] := R[J]; //将大于R[I]的元素后移// J := J - 1 end R[J + 1] := R[0] ; //插入R[I] // end End; //InsertSort // 二、选择排序 1. 基本思想: 每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 2. 排序过程: 【示例】: 初始关键字[49 38 65 97 76 13 27 49] 第一趟排序后13 [38 65 97 76 49 27 49] 第二趟排序后13 27 [65 97 76 49 38 49] 第三趟排序后13 27 38 [97 76 49 65 49] 第四趟排序后13 27 38 49 [49 97 65 76] 第五趟排序后13 27 38 49 49 [97 97 76]

排 列 组 合 公 式 及 排 列 组 合 算 法 ( 2 0 2 0 )

字符串的排列组合算法合集 全排列在笔试面试中很热门,因为它难度适中,既可以考察递归实现,又能进一步考察非递归的实现,便于区分出考生的水平。所以在百度和迅雷的校园招聘以及程序员和软件设计师的考试中都考到了,因此本文对全排列作下总结帮助大家更好的学习和理解。对本文有任何补充之处,欢迎大家指出。 首先来看看题目是如何要求的(百度迅雷校招笔试题)。一、字符串的排列 用C++写一个函数, 如 Foo(const char *str), 打印出 str 的全排列,如 abc 的全排列: abc, acb, bca, dac, cab, cba 一、全排列的递归实现 为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。找到这个规律后,递归的代码就很容易写出来了: view plaincopy #includeiostream?using?namespace?std;?#includeassert.h?v oid?Permutation(char*?pStr,?char*?pBegin)?{?assert(pStr?pBe

gin);?if(*pBegin?==?'0')?printf("%s",pStr);?else?{?for(char *?pCh?=?pBegin;?*pCh?!=?'0';?pCh++)?{?swap(*pBegin,*pCh);?P ermutation(pStr,?pBegin+1);?swap(*pBegin,*pCh);?}?}?}?int?m ain(void)?{?char?str[]?=?"abc";?Permutation(str,str);?retur n?0;?}? 另外一种写法: view plaincopy --k表示当前选取到第几个数,m表示共有多少个数?void?Permutation(char*?pStr,int?k,int?m)?{?assert(pStr); ?if(k?==?m)?{?static?int?num?=?1;?--局部静态变量,用来统计全排列的个数?printf("第%d个排列t%s",num++,pStr);?}?else?{?for(int?i?=?k;?i?=?m;?i++)?{?swa p(*(pStr+k),*(pStr+i));?Permutation(pStr,?k?+?1?,?m);?swap( *(pStr+k),*(pStr+i));?}?}?}?int?main(void)?{?char?str[]?=?" abc";?Permutation(str?,?0?,?strlen(str)-1);?return?0;?}? 如果字符串中有重复字符的话,上面的那个方法肯定不会符合要求的,因此现在要想办法来去掉重复的数列。二、去掉重复的全排列的递归实现 由于全排列就是从第一个数字起每个数分别与它后面的数字交换。我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这二个数就不交换了。如122,第一个数与后面交换得212、221。然后122中第二数就不用与第三个数交换了,但对212,它第二个数

一种改进的中文字符串排序方法

2010,46(19)1引言 字符串排序是自然语言处理中的重要基础技术,排序速度会对相关处理产生很大影响。在新词发现、术语抽取、有意义串检测等领域,排序算法都有广泛应用。在基于大规模语 料的中文高频重复模式提取中,字符串排序已经成为影响重 复模式提取速度的关键技术。 人们对研究排序技术一直很感兴趣,也产生了很多高效 的排序算法[1]。基于比较的排序方法较多,包括:插入排序 (Insertion Sort )、冒泡排序(Bubble Sort )[2]以及快速排序 (Quick Sort )[3]等。插入排序和冒泡排序算法的时间复杂度是O (n 2);快速排序算法是最常用的排序算法,该算法的平均时间 复杂度是O (n lg n ),最坏的情况是O (n 2);桶排序[4-5]方法是一种特殊的排序方法,处理均匀数据效率很高,是O (N )算法,但对 极不均匀数据则退化成复杂度为O (n 2)的插入排序。基数排序 (Radix Sort )[6]算法是一种不基于比较的排序方法,算法的时间复杂度是O (dn )。从理论上看,基数排序算法具有最快的排序速度,但一般应用于整型数值领域,使用范围受到了诸多限制。对中文字符串排序,基本上都是直接使用基于比较的排序方法来实现,很少有针对中文字符串排序的专门研究。何文明等[7]提出了一种针对复杂数据(包括字符串)的分档排序 算法,可以获得比较有针对性的排序效率提升,但针对中文字一种改进的中文字符串排序方法 张海军1,2,3,丁溪源2,朱朝勇2, 3ZHANG Hai-jun 1,2,3,DING Xi-yuan 2,ZHU Chao-yong 2, 31.新疆师范大学计算机科学与技术系,乌鲁木齐830054 2.中国科学院计算机语言信息工程研究中心,北京100097 3.中国科学技术大学计算机科学与技术学院,合肥230027 1.Department of Computer Science and Technology ,Xinjiang Normal University ,Urumqi 830054,China 2.Research Center of Computer &Language Information Engineering ,Chinese Academy of Sciences ,Beijing 100097,China 3.School of Computer Science and Technology ,University of Science and Technology of China ,Hefei 230027,China E-mail :ustczhj@https://www.360docs.net/doc/0c19271851.html, ZHANG Hai-jun ,DING Xi-yuan ,ZHU Chao-yong.Improved sort method for Chinese https://www.360docs.net/doc/0c19271851.html,puter Engineering and Applications ,2010,46(19):129-131. Abstract :At present ,the time complexity of the fastest sort algorithm for Chinese strings is O (n lg n ).Radix sort algorithm ,whose time complexity is O (dn ),is one of the most efficient sort methods ,but it is fit for integer data with identical digits.This paper puts forward a fast transform method used to convert strings to an integer arrays with identical length.The inte-ger arrays representing strings are sorted by radix sort algorithm to achieve rapid sort for Chinese strings.Experiments show that the improved algorithm can quickly sort Chinese strings and its performance is better than that of quick sort algorithm.The relationship between sort time and data size is linear and the time complexity of the algorithm is O (dn ). Key words :Chinese string ;radix sort ;hash table ;time complexity 摘要:对中文字符串排序,最快算法的时间复杂度是O (n lg n )。基数排序算法是目前最快的排序方法之一,时间复杂度是O (dn ),但其一般适用于相同长度的整型数据排序。提出了一种快速的变换方法,将字符串转换为与之等长的整型数组,使用基数排序算法对代表字串的整型数组排序,用以实现对字符串的快速排序。实验表明,提出的算法能快速地进行中文字符串排序,比快速排序算法具有更好的性能,且排序时间与数据规模之间是线性关系,算法的时间复杂度为O (dn )。 关键词:中文字符串;基数排序;散列表;时间复杂度 DOI :10.3778/j.issn.1002-8331.2010.19.037文章编号:1002-8331(2010)19-0129-03文献标识码:A中图分类号:TP391基金项目:国家自然科学基金(the National Natural Science Foundation of China under Grant No.60672149);国家高技术研究发展计划(863) (the National High-Tech Research and Development Plan of China under Grant No.2006AA010109)。 作者简介:张海军(1973-),男,博士研究生,CCF 学生会员,研究方向为自然语言处理,新词汇识别技术;丁溪源(1985-),男,硕士研究生,研究方 向为新词识别技术;朱朝勇(1985-),男,博士研究生,研究方向为自然语言处理,知识库构建技术。 收稿日期:2009-12-28修回日期:2010-03-22?数据库、信号与信息处理? Computer Engineering and Applications 计算机工程与应用129

补充全排列算法C语言实现

字符串全排列算法C语言实现 问题描述: 输入一个字符串,打印出该字符串中字符的所有排列。 输入: 123 输出: 123 132 213 231 312 321 问题分析: 现象分析: 这种问题,从直观感觉就是用递归方法来实现即:把复杂问题逐渐简单化,进而得出具体代码实现。(如何发现一个问题可以使用递归方式来解决?经分析可以发现:M 个数的排列方法与N(N>M)个数的排列方法没有区别,处理方法与数据的个数没有关系。 处理方法的一致性,就可以采用递归)。 3个数(123)排列,第一位1不动,剩下两个数(23)的排列,只要相互颠倒一下,就可以出现关于1开头的所有排列 123 132 把2换到第一位,保持不动,剩下的两个数(13)的排列,只要相互颠倒一下,就可以出现关于2开头的所有排列 213 231 同理,把3换到第一位,可得到 312 321 扩展: 把3个数的所有排列,前面加一个4,就可以得到关于4开头的所有的排列4123 4132 4213 4231 4312 4321 若把4与后续数据中的任意一个数据交换,通过完成对后续三个数的全排列,就可以得到相应的数开头的四数的排列。 总结: 对4个数的排列,可以转换成首位不动,完成对3个数的排列 对3个数的排列,可以转换成首位不动,完成对2个数的排列 对2个数的排列,可以转换成首位不动,完成对1个数的排列 对于1个数,无排列,直接输出结果 算法实现说明:

对n个数的排列,分成两步: (1)首位不动,完成对n-1个数的排列, (2)循环将后续其他数换到首位,再次进行n-1个数的排列 注:排列完成后,最终的串要与原串相同 C语言代码实现: #include #include //将串左移一位,首位存到末尾。 void shift( char *s ) { if ( !s||!s[0] ) return ; //security code . null string char ch=s[0]; int i=0; while( s[++i] ) s[i-1]=s[i] ; s[i-1]=ch; } //本函数对于一个已排序好的数据进行全排列 void permutation(char list[], int head ) { int i,len; len=strlen(list) ; if ( len-head == 1 ) //后续没有再排列的,则输出排列数据 { printf( "%s\n", list ); } else { for (i = k; i

53.String sort 字符串排序的几种方法

String sort的几种方法 简介 在之前的一些排序算法中,主要是对一些数值的类型比较的比较多一点。而对于字符串类型来说,它有一些特殊的性质。如果按照传统的排序方法,对于字符串的比较性能其实还取决于字符串的长度以及相似程度。实际上,对于一些字符集的取值在一个比较小的范围内的情况,我们可以有一些比较高效率的算法。这里针对这些特殊的情况进行讨论。 假设给定的排序集合里元素,也就是每个字符都是在一个比较有限的范围里,比如说256个字符范围内。那么,我们可以利用这个特性做一些高效的处理。联想到之前讨论过的counting sort和radix sort方法。这里就是利用了这个特性。 Key-Indexed counting 在之前讨论couting sort的文章里,曾经针对需要排序的元素为数字的情况进行过讨论。counting sort成立的一个前提是它里面所有的元素取值是在一个固定的范围内。假设这个数组里元素能取的最大值是k,那么每次我们要排序的时候只需要声明一个长度为k的数组a。每次碰到一个元素i就将a[i]对应的值加1。这样就统计出来了所有从小到大的元素的值的分布。剩下的就只是从小到达把这些值重新排列输出就可以了。 当然,在一些数字有一定长度而且它们的长度都一样的情况下。我们可以利用从高到低或者从低到高位逐位排序的方式来对数组进行排序。这就是radix sort的基本思路。它本质上就是在每一位的排序上都使用了couting sort。 借鉴前面对于数字的排序,我们对于字符串数组的排序也可以采用类似的方式: Java代码 1.int[] count = new int[R + 1]; 2.//计算每个字符出现的频率 3.for(int i = 0; i < n; i++) 4. count[a[i].charAt(d) + 1]++; 5.//将每个字符出现的频率转换为所在的索引 6.for(int r = 0; r < R; r++) 7. count[r + 1] += count[r]; 8.//将字符分布到具体的数组位置 9.for(int i = 0; i < n; i++) 10. aux[count[a[i].charAt(d)]++] = a[i]; 11.//将结果拷贝回数组 12.for(int i = 0; i < n; i++) 13. a[i] = aux[i]; 上述代码里的R表示当前字符的取值范围。在R值不大的时候它的效率还是相当可观的。在这个计数排序的基础上,我们可以得到一些不同的排序算法。 LSD sort 一种最典型的方法就是从最低位向最高位的方式依次排序,这种和前面的radix sort的思路基本上完全一样。不过在前面的基础上针对字符的情况稍微做一点修改。详细的代码实现如下: Java代码 1.public class LSD {

全排列生成算法

全排列的生成算法对于给左的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来。字典序法按照字典序求下一个排列的算法广例字符集{1,2,3},较小的数字较先,这样按字典序生成的全排列是:123,132,213,231,312,321o注意一个全排列可看做一个字符串,字符串可有前缀、后缀/生成给泄全排列的下一个排列所谓一个全排列的下一个排列就是这一个排列与下一个排列之间没有其他的排列。这就要求这一个排列与下一个排列有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。广例839647521是1—9的排列。1—9的排列最前而的是123456789,最后而的是987654321,从右向左扫描若都是增的,就到了987654321,也就没有下一个了。否则找出第一次出现下降的位置。算法:由P1P2...Pn生成的下一个排列的算法如下:1求j=max{j| Pj-I

Excel中三种主要的排序方法

Excel中三种主要的排序方法 陈宇2006年09月25日17:07 重庆科技咨询中心专稿 在Excel中通常有大量的数据存在,要让这些数据显得更加直观,就必须有一个合理的排序。在Excel中主要有三种排序方法,分别为文本排序、数值排序和自定义排序,本文将具体介绍其使用方法。 在Excel中通常有大量的数据存在,要让这些数据显得更加直观,就必须有一个合理的排序。在Excel中主要有三种排序方法,分别为文本排序、数值排序和自定义排序,以下将具体介绍其使用方法。 文本排序 某些时候需要按姓氏笔划为文本排序,Excel提供了比较好的解决办法。比如您要将数据表按所有姓名的笔划排序,可以使用以下方法: 选中排序关键字所在列(或行)的首个单元格,单击Excel“数据”菜单下的“排序”命令,再单击其中的“选项”按钮。选中“排序选项”对话框“方法”下的“笔画排序”,再根据数据排列方向选择“按行排序”或“按列排序”,“确定”后回到“排序”对话框。如果您的数据带有标题行(如“姓名”),则应选中“有标题行”,然后打开“主要关键字”下拉列表,选择其中的“姓名”,选中排序方式(“升序”或“降序”)后“确定”,表中的所有数据就会据此重新排列。 数值排序 RANK函数 RANK函数是Excel计算序数的主要工具,它的语法为:RANK (number,ref,order),其中number为参与计算的数字或含有数字的单元格,ref是对参与计算的数字单元格区域的绝对引用,order是用来说明排序方式的数字(order为0或空,则以降序排列,反之按升序排列)。 需要注意的是:相同数值用RANK函数计算得到的序数相同,但会导致后续数字的序数空缺。 COUNTIF函数 COUNTIF函数可以统计某一区域中符合条件的单元格数目,它的语法为COUNTIF(range,criteria)。其中range为参与统计的单元格区域,criteria是以数字、表达式或文本形式定义的条件。其中数字可以直接写入,表达式和文本必须加引号。 IF函数 Excel自身带有排序功能,可使数据以降序或升序方式重新排列。如果将它与IF函数结合,可以计算出没有空缺的排名。 自定义排序 在某些情况下,已有的排序规则是不能满足用户要求的,这时候可以用定义排序规则的方法解决:首先单击Excel“工具”菜单下的“选项”命令,打开“选项”对话框中的“自定义序列”选项卡。选中左边“自定义序列”下的“新序列”,光标就会在右边的“输入序列”框内闪动,您就可以输入规则。比如你要按“一班”、“二班”来进行统计,那么就输入“一班”、“二班”等自定义序列了,输入的每个序列之间要用英文逗号分隔,或者每输入一个序列就敲回车。如果序列已经存在于工作表中,可以选中序列所在的单元格区域单击“导入”,这些序列就会被自动加入“输入序列”框。无论采用以上哪种方法,单击“添加”按钮即可将序列放入“自定义序列”中备用。 当需要排序时,只要打开“排序选项”对话框中的“自定义排序次序”下拉列表,选中前面定义的排序规则,其他选项保持不动。回到“排序”对话框后根据需要选择“升序”或“降序”,“确定”后即可完成数据的自定义排序。

排 列 组 合 公 式 及 排 列 组 合 算 法

排列组合——排列公式的推理和组合 加法原理和乘法原理,是排列组合中的二条基本原理,在解决计数问题中经常运用。掌握这两条原理,并能正确区分他们,至关重要。 加法原理 若完成一件事情有3类方式,其中第一类方式有1种方法,第二类方式有3种方法,第三类有2种方法,这些方法都不相同,但任选一种方法都可以完成此事,则完成这件事情共有1+3+2=6种方法,这一原理称为加法原理。例如:从甲地到乙地有三类方式,一是汽车,二是火车,三是飞机。若一天中汽车有2班,火车有4班,飞机有一班,那么从甲地到乙地共有多少种不同的走法。共有2+4+1=7种。 乘法原理 若完成一件事情分r个步骤,其中第一个步骤有m1种方法,第二个步骤有m2种方法……第步骤共有mr种方法,各步骤连续或同时完成,这件事才算完成,则完成这件事共有m1*m2*……*mr种方法。例如:从甲地到丙地必须经过乙地。从甲地到乙地有4条路线,从乙地到丙地有3条路线,问从甲地到丙地共有多少种不同的走法?解:要从甲地到达丙地,必须经过两个步骤:先从甲地到乙地,有4条路线;再从乙地到丙地,有3条路线。只有这两个步骤都完成了,才能完成这种事情,缺少哪一个步骤都不行。因此从甲地到丙地共有4*3=12种走法。 加法原理和乘法原理的区别

以上两个基本原理在排列组合问题中将会反复使用。这两个原理回答的都是关于完成一件事情的不同方法的种数问题,但是又有根本区别。加法原理针对的是“分类”问题,若完成一件事情有多类方式,每一类方式的各种方法相互独立,用其中任何一种方法都可以完成这件事情,则用加法原理;而乘法原理针对的是“分步”问题,若完成一件事情必须依次经过多个步骤,每一个步骤的各种方法相互依存,只有各种步骤都完成才算做完成这种事情,则这时用乘法原理。 排列数公式推理过程 例:用1、2、3这3个数字可以组成多少个数字十位和个位不重复的两位数?解:要组成数字不重复的两位数,需要经过两个步骤:第一步确定十位上的数,数字1、2、3都可以放在十位上,共有3种方法;第二步确定个位上的数,因为要求个位数与十位数不能重复,所以个位上的数,只能从三个数字中去掉十位数后所剩的两个数字中任选一个,共有2种方法。只有十位和个位上的数都确定了,才能组成数字不重复的两位数,这两个步骤缺少哪一个都不行。因此,根据乘法原理,3*2=6. 上例中,我们把数字1、2、3称为元素。组成数字不重复的两位数这个问题,从3个不同的元素中任取2个,然后按顺序排成一列数,由于这样的排列与数字不重复的两位数是一一对应的,因此求数字不重复的两位数的个数等同于求这样的排列个数。 推理过程:从n个不同元素中取出m个不同元素排成一列,必须经过m 个步骤。第一步,确定第1个位置上的元素,可以从这n个元素中任取1个放在这个位置上,共有n种方法,即n-(1-1)括号内为位置数减1;第

Java中升序降序输出String字符

package comparator001; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; public class TestArrayAndLinkedList { public static void main(String args[]) { List lit = Arrays.asList("red","ccc","sss","bbb","aaa","green","blue"); Collections.sort(lit);//升序排序 /** * 输出结果:[aaa, bbb, blue, ccc, green, red, sss] * */ System.out.println(lit); System.out.println(); List list = Arrays.asList("red","ccc","sss","bbb","aaa","green","blue"); Collections.sort(list,Collections.reverseOrder());//降序排列 System.out.println(list); // List ssrray = new ArrayList(); // // ssrray.add(1); // ssrray.add(2); // ssrray.add(3); // ssrray.add(4); // ssrray.add(1); // ssrray.add(0, 10);

Excel排序的三种方法

Excel排序的三种方法 2003-05-27 17:14来源:电脑报作者:责任编辑:·yesky评论(188) 在用Excel 2000/2002处理数据的时候,经常要对数据进行排序处理。我们最常用、最快捷的方法就是使用工具栏的排序按钮。但是,面对各式各样的表格和各种需要,只用这一种方法显然不够。 一、一般排序 在图1中,要对英语成绩进行排序,可在英语这列中单击任一单元格。然后单击工具栏中的升序或降序按钮,可完成排序。 注意:若把排序的一列全部选中后再使用上面的操作,排序将只发生在这一列中,其它列的数据排列将保持不变,其结果可能会破坏原始记录结构,造成数据错误! 二、菜单排序 如果我们把图1中的数据稍微改动一下,如在第一行的前面插入一行,并输入“石中2000(6)班成绩表”,并把A1~H1这几个单元格合并,然后再用一般的排序方法排序,会提示不能成功,如图2。

如果对这样的表格排序,可选中要排序的所有数据,包括标题行(学号、姓名等所在的行),然后单击“数据/排序”菜单,弹出如图3所示窗口。 在主关键字的下拉列表中,选择要排序的列,如英语,在右侧选择“升序排列”或“降序排列”。至于次要关键字和第三关键字可添可不添,但是它起到什么样的作用呢?在这儿举个例子,如果按英语排序,有两个学生都得了96分,但又必须分出高低,这样我们可选择数学成绩作为排名次的次要标准,谁得分高谁排在前面,那么这儿的次要关键字就是数学。一切做完后,单击“确定”就可以看到结果了。 三、自定义排序 在这个成绩表中,如果我们想按职务这列排序,如先后顺序是:团委书记、班长、副班长、学习委员、学生。但是不管用上面的哪种方法都不会得到我们需要的结果。在这儿利用Excel 2000/2002提供的自定义排序,就可以解决这个问题。 1.在“工具”菜单上,单击“选项”,再单击“自定义序列”选项。 2.在右侧的输入序列框中依次输入团委书记、班长、副班长、学习委员、学生,然后单击“确定”。 3.选中排序的数据,在“数据”菜单上单击“排序”,在“主要关键字”框中,单击需要排序的列,如职务。

c语言递归算法实现数列全排列

1、数列全排列递归算法; 2、在不打印所有全排列时,数列长度分别为10、11、12、13时全排列花费时间测试,修改N的值重新编译即可运行测试; 3、如果需要打印全排列,打开perm函数中的注释掉的两行printf语句即可。

#include #define N 10 int a[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; void swap(int one, int two) { int tmp = a[one]; a[one] = a[two]; a[two] = tmp; } void perm(int *list, int begin, int end)

{ int i = 0; if (begin == end){ for ( i = 0; i < N ; i++){ //printf("%d", list[i]); } //printf("\n"); } else{ for (i = begin; i <= end; i++) { swap(begin,i); perm(list,begin+1,end); swap(begin,i); } } } int main(int argc, char *argv[]) { int *list=a; int i; perm(list, 0, N-1); for (i = 0; i < N; i++){ printf("%d", list[i]); } return 0; }

c语言 数组排序 字符串排序 函数实现

1.数组倒叙 #include void show(int *a,int len) { int i; for(i=0;i

2.字符串排序 #include #include int main() { char *a[]={"aaaaaaa","ddddddd","eeeee","cccccc"}; int i; int len=sizeof a/sizeof *a; for(i=0;i0) { a[y]=(char *)((int )a[y]^(int)a[y+1]); a[y+1]=(char *)((int )a[y]^(int)a[y+1]); a[y]=(char *)((int )a[y]^(int)a[y+1]); } for(i=0;i

c语言数组排序字符串排序函数实现

1.数组倒叙#include void show(int *a,int len) { int i; for(i=0;i

} return a; } int main() { int l,i; int a[]={1,2,3,4,5,6,7,8}; l=sizeof a/sizeof *a; show(a,l); int *b=reverse(a,l); show(b,l); } 2.字符串排序 #include #include int main() {

char *a[]={"aaaaaaa","ddddddd","eeeee","cccccc"}; int i; int len=sizeof a/sizeof *a; for(i=0;i0) { a[y]=(char *)((int )a[y]^(int)a[y+1]); a[y+1]=(char *)((int )a[y]^(int)a[y+1]); a[y]=(char *)((int )a[y]^(int)a[y+1]); } for(i=0;i

相关文档
最新文档