很重要的排列字符画生成器 在线(列出几个字符的所有排

条形码又称条码、一维码,是将字符按照特定的规则转化成二进制后,描绘成一个宽度不等的多个黑条和空白,按照一定的编码规则排列的图形标识符,条形码现在应用相当广泛,一出门,随便翻一样东西,可能都有它的身影。
条形码的编码规则五花八门,算算都有数十种,各种都有它特有的空间里发挥作用。
本条形码生成器可生成条形码的种类有:Code128、EAN128、Code39、Code93、库德巴码、交叉25码(interleaved 2 of 5,ITF)、工业25码(Industrial 2 of 5 Code)、矩阵25码(Matrix 2 of 5 Code)、MSI条码、Code11码、EAN-13商品条码、EAN-8商品条码、UPC-A商品条码、UPC-E商品条码、国际标准书号(ISBN)条码等。
条形码生成的字符比较有限,太多的字符,图形会拉得很长,扫码器可能就识别不完了,在这里限制只能输入25个字符,超过的将自动忽略。
分辨率设置时限制小于600,一般图片的分辨率常设置为72px、96px、203px、305px等。
高度是单条带宽度的倍数,设定范围是1-100的整数。(由于EAN-13条码和EAN-8条码比较特殊,国家标准中规定了相应的高度,所以高度设定无效),所生成条码仅适于生活娱乐,不可用于商业及不法用途。
打印可行性仅在chrome浏览器上测试过;若要保存图片,可右键图片,选择"图片另存为..."
原文链接:
版权所有:& ||
|| 电子邮箱:算法练习 - 字符串的全排列(字典序排列)
输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串abc, acb, bac, bca, cab, cba。
穷举与递归
又是一个经典问题,最容易想到的解决方法仍然是穷举(我实在是太爱穷举法了,每当被问到算法问题不知道如何解决的时候,总可以祭出穷举大旗,从而多争取3分钟的思考时间)。穷举虽好,但它大多数情况下都不是被需要的那个答案,是因为看起来代码太Low不够高大上吗?
在这种情况下,穷举法裹着貂皮大衣的亲戚——递归就出现了。虽然空间复杂度和时间复杂度没有任何改进,而且还增加了系统开销(关于递归法的系统开销不在这里讨论,之后再找专门的时间阐述),但是就是因为长得好看(代码看起来精炼),递归的B格儿就高了很多。
递归法对于这个题目同样非常适用,基本思路就是固定一个字符,然后对剩余的字符做全排列……不赘述,请自己想。如果你也跟我一样永远想不明白递归,那就画画图,写写代码,debug一下,每天花3-4个小时,静下心来仔细捉摸,总(ye)会(bu)想(hui)明白的。贴一段July和他伙伴们在《程序员编程艺术:面试和算法心得》中的代码实现,供做噩梦时使用。p.s. 我已加了注释
* Permute full array of input string by general recusion
* @ char* perm [in/out] The string need to do permutation
* @ int from [in] The start position of the string
* @ int to [in] The end position of the string
void CalcAllPermutation(char* perm, int from, int to)
if (to &= 1)
if (from == to)
//all characters has been permuted
for (int i = 0; i &= i++)
cout && perm[i];
// always select one character, then full array the left ones.
for (int j = j &= j++)
swap(perm[j], perm[from]); //swap the selected character to the beginning of string
CalcAllPermutation(perm, from + 1, to); // Permute left characters in full array.
swap(perm[j], perm[from]); //recovery the string to original one (swap the selected character back to its position.)
这是一个比递归更有趣的答案,不知道算不算经典解法,起码开拓了思路,跟每一次接触新鲜的算法一样,仍然想了半天的时间,因此照例把思考过程更细致的记录下来(虽然July和他伙伴们在《程序员编程艺术:面试和算法心得》中已经说了很多),再加上一些小修改。
字典序,顾名思义,就是按照字典的顺序进行排列。根据维基百科的定义:给定两个偏序集A和B,(a,b)和(a′,b′)属于笛卡尔集 A × B,则字典序定义为(a,b) ≤ (a′,b′) 当且仅当 a & a′ 或 (a = a′ 且 b ≤ b′)。所以给定两个字符串,逐个字符比较,那么先出现较小字符的那个串字典顺序小,如果字符一直相等,较短的串字典顺序小。例如:abc & abcd &
abde & afab。
总结一下,字典序排序其实就是同一组字符组成的一系列字符串,
起点: 字典序最小的排列, 1~n , 例如12345
终点: 字典序最大的排列,n~1, 例如54321
过程: 从当前字符串排列生成字典序刚好比它大的下一个排列,比如12345的字典序下一个排列是12354
现在来进一步分析一下算法实现,其实对于字典序排列,关键点就是找到“下一个排列”。基本的查找方法
假定现有字符串(A)x(B),它的下一个排列是:(A)y(B’),其中A、B和B’是“字符串”(可能为空),x和y是“字符”,前缀相同,都是A,且一定有y & x。那么,为使下一个排列字典顺序尽可能小,必有:
A尽可能长 (A越长,那么B‘就越短,从而y所在的位越低,很明显的同一个字符放在低位肯定比放在高位要小,比如:100&10& 1,
abc&aac&aaa)y尽可能小 (同一个位置上,字符越小整个字符串的字典序越小,比如:131&121, acd&abc)B'里的字符按由小到大递增排列 (小朋友都懂的道理不解释)现在的问题是如何找到“x”和“y”?
举个例子,现在我们要找21543的下一个排列,我们可以从左至右逐个扫描每个数,看哪个能增大(至于如何判定能增大,是根据如果一个数右面有比它大的数存在,那么这个数就能增大),我们可以看到最后一个能增大的数是:x = 1。而1应该增大到多少?1能增大到它右面比它大的那一系列数中最小的那个数,即:y = 3,故此时21543的下一个排列应该变为23xxx,显然 xxx(对应之前的B’)应由小到大排,于是我们最终找到比“21543”大,但字典顺序尽量小的23145,找到的23145刚好比21543大。
抽象概括一下上面的例子就是“二找、一交换、一翻转”。
一找:找到排列中最后(最右)一个升序的首位位置i,x = ai
二找:找到排列中第i位右边最后一个比ai 大的位置j,y = aj
一交换:交换x,y
一翻转:把第(i+ 1)位到最后的部分翻转*升序:相邻两个位置ai & ai+1,ai 称作该升序的首位
找21543的下一个排列,套用“二找、一交换、一翻转”就是
一找: 找到排列中最后(最右)一个升序的首位, x = 1二找: 找到排列中1的右边最后一个比1大的位置,y = 3一交换:1和3交换,得23541一翻转:翻转541,得23145道理讲完了,但是你真的懂了吗?反正本人看到这里又看了算法之后,仍然懵懵懂懂(请原谅我的智商吧,其实我自己也挺着急的,妈妈已经急哭,表示对我放弃治疗了)。因此,下面的部分很重要。
首先来看第一找“找到排列中最后(最右)一个升序的首位位置i,x = ai”
这意味着什么?这意味着字符串在x之后所有字符都是降序排列的,如下图。在找到x=1之前,543已经达到了最大字典序,因此不可能通过改变543的顺序得到更大的字符串。
那么为什么不是修改首位的“2”呢?还记得前面介绍的字符串(A)x(B)的下一个排列是(A)y(B’)的方法吗?,A要尽可能长。对“1”进行操作正式保证了A尽可能长。
接下来,看一下第二找和一交换:“找到排列中第i位右边最后一个比ai 大的位置j,y = aj”,“交换x,y”
说完了“A要尽可能长”,现在该说y要尽可能小了。为什么“第二找”和“一交换”之后,y就最小了呢?既然首位的“2”是不在范围内的,而“1”(即x)是要被交换的,那么y只能来自“5”,“4”,'3“,因为543是降序排列的(注意,x可是找到的字符串中最后一个升序的首位哟),因此“5”,“4”,'3“中比”1“(即x)大的最小的字符就是y。于是y=3。交换x,y之后,即得到新的字符串(A)y(B')
此时的B'仍然不是我们最终需要的B',因为它还不满足最后一个条件B'里的字符按由小到大递增排列。为了做到这一点,于是有了最后的“一翻转”。那么为什么简单的翻转之后B'里的字符就按照由小到大的顺序排列了呢?
我们在来回顾一下B和B‘的确定过程。首先,B是一个降序排列的字符串;然后我们在B中找到了比x小的最小的y(此处有些绕,自己写几个字符串就一目了然了),也就是说y的右侧如果还有字符的话也一定比x小(因为B是降序),接下来交换x和y得到B',因此B’也是降序的。对于一个降序的字符串来说,翻转之后即为升序排列。于是我们得到了最终的(A)y(B'),即23145。
好了,该讲的都讲完了,现在看代码
* Find out the next (bigger) permutation of current string.
* @ char* perm [in/out] String
* @ int num [in] The length of string.
bool FindNextPermutation(char* perm, int num)
int i = 0;
for(i = num - 2; (perm[i] &= perm[i+1]) && i &= 0; --i)
; // Find x
// The input string is a single character
int j = 0;
for(j = num - 1; (j & i) && perm[j] &= perm[i]; --j)
; // Find y
swap(perm[i], perm[j]);
// swap x and y
reverse(perm + i + 1, perm + num); // reverse B'
这段代码实现了从当前字符串生成字典序刚好比它大的下一个排列,但是如果我们拿到的字符串不是字典序最小的排列,该如何处理呢?两种方法
对原始字符串进行排序,将原始字符串转换为字典序最小的排列后,再通过字典序排序进行全排列。这样做的好处是实现简单,缺点是要多做一次字符串排序。关于排序算法不在本文讨论范围,这里我直接使用了STL的sort函数
void CalcByDictionary(const string &str)
char* perm = const_cast&char*&(str.c_str());
sort(perm, perm+str.size());
cout&&str&&
while(true)
if(!FindNextPermutation(perm, str.size()))
既然给定一个字符串我们可以生成字典序刚好比它大的下一个排列,那么就可以生成字典序刚好比它小的前一个排列。具体方法请自行思考(将前面讲的内容全部反过来想)。这样做的优点是节省了一次字符串排序,缺点是烧脑(还要照葫芦画瓢,实现一个向前查找的函数)
void CalcByDictionary(const string &str)
string s =
char* perm = const_cast&char*&(str.c_str());
cout&&str&&
int num = str.size();
while(true)
if(!FindPrePermutation(perm, num))
cout&&str&&
perm = const_cast&char*&(s.c_str());
while(true)
if(!FindNextPermutation(perm, num))
&pre name="code" class="cpp"&/*
* Find out the previous (smaller) permutation of current string.
* @ char* perm [in/out] String
* @ int num [in] The length of string.
bool FindPrePermutation(char* perm, int num)
int i = 0;
for(i = num - 2; (perm[i] &= perm[i+1]) && i &= 0; --i)
int j = 0;
for(j = num - 1; (j & i) && perm[j] &= perm[i]; --j)
swap(perm[i], perm[j]);
reverse(perm + i + 1, perm + num);
最近一直在看July和他伙伴们的《程序员编程艺术:面试和算法心得》,收获良多。在学习的过程中发现,虽然原书讲解的很细致,但是真正理解仍然需要花费大量的思考和实践。因此做了这个系列的文章,只是希望将自己的思考记录下来,供以后查阅。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
10亿个字符串的排序问题
摘要:一、问题描述有一个大文件,里面有十亿个字符串,乱序的,要求将这些字符串以字典的顺序排好序二、解决思路将大文件切割成小文件,每个小文件内归并排序;对所有的小文件进行归并排序——多重归并排序三、解决方案3.1&模拟产生10亿个随机字符串public&static&void&generateDate()&throws&IOException&{BufferedWriter&writer&=&n
一、问题描述
有一个大文件,里面有十亿个字符串,乱序的,要求将这些字符串以字典的顺序排好序
二、解决思路
将大文件切割成小文件,每个小文件内归并排序;
对所有的小文件进行归并排序——多重归并排序
三、解决方案
3.1&模拟产生10亿个随机字符串
public&static&void&generateDate()&throws&IOException&{
BufferedWriter&writer&=&new&BufferedWriter(new&FileWriter(ORIGINALPATH));
Random&random&=&new&Random();
StringBuffer&buffer&=&new&StringBuffer(
&abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&);
int&range&=&buffer.length();
int&length&=&1;
for&(int&i&=&0;&i&&&BIGDATALENGTH;&i++)&{
StringBuffer&sb&=&new&StringBuffer();
length&=&random.nextInt(20)+1;
// System.out.println(&length---&&+length);
for&(int&j&=&0;&j&&&&j++)&{
// System.out.println(&j---&&+j);
sb.append(buffer.charAt(random.nextInt(range)));
System.out.println(&sb----&&+sb);
writer.write(sb.toString()&+&&/n&);
writer.close();
3.2&对大文件进行切割
*&将原始数据分成几块&并排序&再保存到临时文件
*&@throws&IOException
public&static&void&splitData()&throws&IOException&{
@SuppressWarnings(&resource&)
BufferedReader&br&=&new&BufferedReader(new&FileReader(ORIGINALPATH));
tempFiles&=&new&File[BIGDATALENGTH&/&TEMPFILELENGTH];//将会产生的临时文件列表
for&(int&i&=&0;&i&&&tempFiles.&i++)&{
tempFiles[i]&=&new&File(TEMPFILEPATH&+&&TempFile&&+&i&+&&.txt&);
BufferedWriter&writer&=&new&BufferedWriter(new&FileWriter(tempFiles[i]));
HashMap&Integer,String&&hashMap&=&new&HashMap&Integer,String&();//未排序
//每次读出TEMPFILELENGTH个文件&保存到smallLine中
for&(int&j&=&1;&j&&=&TEMPFILELENGTH;&j++)&{
String&text&=&
if&((text&=&br.readLine())&!=&null)&{
hashMap.put(j,&text);
hashMap&=&MergeSort.sort(hashMap);
for(int&k=1;&k&=TEMPFILELENGTH;&k++){
writer.write(String.valueOf(hashMap.get(k))
+&System.getProperty(&line.separator&));
//System.getProperty(&line.separator&)相当于/n
writer.close();
3.3&对小文件进行递归归并
*&多路归并排序
*&@param&files
*&@throws&IOException
public&static&void&multiWaysMergeSort(String[]&files)&throws&IOException&{
System.out.println(&归并文件-----第&&+mergeSortCount+&&次-----&);
//当最后只有一个文件的时候&数据已经排序成功&直接复制保存到结果文件
if&(files.length&==&1)&{
String&lastFilePath&=&LASTFILEPATH&+&LASTFILENAME;
copyFile(files[0],&lastFilePath,&false);
//deleteFile(files[0]);
for&(int&i&=&0;&i&&&files.&i+=2)&{
//开始合并两个相邻的文件&所以一次跳两个
if&(i&==&files.length&-&1)&{
//这时候已经只剩下最后一个文件了&不需要合并&本趟归并结束
renameFile(files[i],&i);
//将br1&和&br2&写入到Write
BufferedReader&br1&=&new&BufferedReader(new&FileReader(files[i]));
BufferedReader&br2&=&new&BufferedReader(new&FileReader(files[i&+&1]));
BufferedWriter&writer&=&new&BufferedWriter(new&FileWriter(TEMPFILEPATH&+&&last_&&+&mergeSortCount&+&&_&&+&i&+&&.txt&));
String&s1&=&br1.readLine();
String&s2&=&br2.readLine();
while&(s1&!=&null&||&s2&!=&null)&{
if&(s1&!=&null&&;&;&s2&!=&null)&{
//都不为空&才有比较的必要
int&mergeResult&=&s1.compareTo(s2);
if&(mergeResult&&&0)&{//s1在s2后面
writer.write(s2);
writer.write(System.getProperty(&line.separator&));
s2&=&br2.readLine();
if&(mergeResult&==&0)&{//s1=s2
writer.write(s1); writer.write(System.getProperty(&line.separator&));
writer.write(s2); writer.write(System.getProperty(&line.separator&));
// System.out.println(&write&time&:&&&+&writeTime++);
s1&=&br1.readLine();
s2&=&br2.readLine();
if&(mergeResult&&&0)&{//s1在s2前面
writer.write(s1); writer.write(System.getProperty(&line.separator&));
s1&=&br1.readLine();
if&(s1&==&null&&;&;&s2&!=&null)&{
writer.write(s2);
writer.write(System.getProperty(&line.separator&));
s2&=&br2.readLine();
if&(s2&==&null&&;&;&s1&!=&null)&{
writer.write(s1);
writer.write(System.getProperty(&line.separator&));
s1&=&br1.readLine();
br1.close();
br2.close();
// deleteFile(files[i]);
// deleteFile(files[i&+&1]);
writer.close();
mergeSortCount++;
multiWaysMergeSort(getTempFiles(&last_&&+&(mergeSortCount-1)&+&&_&));
3.4&运行结果分析
①&生成 10 亿个随机字符串,时间太久了,,&字符串长度随机在 [1,&20] 之间时,文件大小大概在 10.7&GB&(11,500,161,591& 字节 )
②&切割成小文件,小文件内归并排序,每个文件内的数据 100 万条时,随机选取五个排序时间如下:
一共发生了 & 次对比 一共发生了& & 次交换 执行时间为 3545 毫秒
一共发生了 & 次对比 一共发生了& & 次交换 执行时间为 3512 毫秒
一共发生了 & 次对比 一共发生了& & 次交换 执行时间为 3497 毫秒
一共发生了 & 次对比 一共发生了& & 次交换 执行时间为 3497 毫秒
一共发生了 & 次对比 一共发生了& & 次交换 执行时间为 3981 毫秒
总共 1000 个文件切割耗时为
切割小文件所用时间 ---&4341734ms---&s---&72.36m---&1.206h
③&&小文件递归归并, 1000 个文件,
共发生了 10 次归并,
产生临时文件总共 1999 个,
总大小为 127.8&GB&(137,201,789,278& 字节 ) ,
产生结果文件 11.6&GB&(12,500,161,591& 字节 )
比源文件多了 10 亿个字节 ......
总耗时为 ---&7374129ms---&s---&122.9m---&2.048h
不得不提的是,最后执行结果成功,也不枉我苦苦等待
四、相关技术
4.1&归并排序
排序原理不多介绍,各种到处都有,如果一时不记得,看下面的原理图。秒懂。
4.2&文件读写
本程序很重要的一点就是对于文件的读写,Buffer的文件读写可以很大程度的改善速率
BufferedWriter&writer&=&new&BufferedWriter(new&FileWriter(PATH));
writer.write(&hhf/n&);
BufferedReader&br&=&new&BufferedReader(new&FileReader(PATH));
text&=&br.readLine()
五、关于优化
5.1分小文件时优化
前提:数据均匀,保证每个小文件大小不会超过内存的容量
处理:在分数据到小文件时,按字符串按首字母将其分到指定文件中,如A-C分配到1.txt,D-F分配到2.txt.......
优点:只需要小文件内数据排序,排序号后,即可将1.txt、2.txt、3.txt直接连接起来,极大的缩短了归并时间,相当于把递归归并变成了文件连接而已
缺点:前提不是很容易把握,若有一个小文件内的数据量大于内存的大小,则排序失败,存在一定的风险
5.2小文件内排序时优化
前提:保证每个小文件内数据量比较不是特别的大
处理:将小文件内的数据进行快速排序
优点:快排的时间效率是高于归并的
以下是测试数据
排序数量级 && 10
归并排序 7ms 71ms 3331ms
快速排序 6ms 52ms java.lang.StackOverflowError
缺点:缺点已经显示在测试数据内了,小文件内的数据量过大就可能导致当前线程的栈满
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
邮箱低至5折
推荐购买再奖现金,最高25%
&200元/3月起
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
10亿个字符串的排序问题相关信息,包括
的信息,所有10亿个字符串的排序问题相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
International鍗氬?鍒嗙被锛}

我要回帖

更多关于 字符画生成器 在线 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信