队列
队列(queue)是一个线性集合,它在一端添加元素,在另一端删除元素。所以可以说队列元素的处理是先进先出(first in, first out, FIFO)的方式。队列中元素删除的次序与它们进入队列的次序相同,就像日常生活中的排队一样,顾客刚到达时排在队尾(tail / rear),队列最前面的人先出队接受服务,后面的人依次向队头(head / front)移动。
与另一种数据结构栈相比较,在栈中,只在集合的一端进行操作处理,而在队列中,两端都有操作。入队(enqueue)是指在队尾添加新元素,而出队(dequeue)是指从队头删除元素,first操作类似栈操作的peek,它检测队头元素,但并不从集合中删除它。
注意对于集合操作来说,这里的命名并不是通用的。有时enqueue操作也被称为add或insert,dequeue操作有时称为remove或serve,first操作有时称为front。
下面简单实现一个队列实例来解决问题。
Caesar密码将字符串信息中的每个英文字符按照字典的顺序移动k位,例如k=3时,在加密时每个字符向前移动3位,a替换为d,b替换为e,c替换为f,以此类推,字母表的最后就绕回最前面。对信息解密时,每个字符就向后移动同样的位数,如k=3,加密信息“vlpsolflwb iroorzv frpsohalwb”就可以解密得到“simplicity follows complexity”。
但是这样的密码显然很容易被破解,因为它只有26种可能的移位方案。而如果使用重复变化的k值,就可以改进这个编码技术。即对每一位字符循环使用一个若干长度的k值表,让每个字符移动的位数有所不同。例如k值表为[3 7 8 4] 时,第一个字符移动3位,第二个字符移动7位,第三个字符移动8位,第四个字符移动4位,第五个字符移动3位,第六个字符移动7位……以此类推。
实现使用重复的k值对文本进行加密和解密。将整型k保存在队列中,使用一个时从队头拿出,使用完再将它放回队尾,如此即可实现循环重复使用。
import javafoundations;
public class Codes
{
public static void main(String[] args)
{
int[] key = {5,12,-3,8,-9,4,10}
Integer keyValue;
String encoded = “”,decoded = “”;
String message = “With great power comes great responsibility.”
CircularArrayQue<Integer> keyQueue1 = new CirculaArrayQueue<Integer>();
CircularArrayQue<Integer> keyQueue2 = new CirculaArrayQueue<Integer>();
//为什么要建两个队列?其中一个保存key的副本便于解码
for (int scan=0; scan<key.length; scan++) //载入key值
{
keyQueue1.enqueue(new Integer(key[scan]));
keyQueue2.enqueue(new Integer(key[scan]));
}
for (int scan=0; scan<message.length; scan++)
{
keyValue = keyQueue1.dequeue(); //当前k值
encoded += (char)((int)message.charAt(scan) + keyValue.intValue()); //Unicode字符集
keyQueue1.enqueue(keyValue); //放入队尾
}
System.out.println(“Encoded Message:\n” + encoded + “\n”);
for (int scan=0; scan < encoded.length(); scan++)
{
keyValue = keyQueue2.dequeue();
decoded += (char)((int)encoded.charAt(scan) - keyValue.intValue());
keyQueue2.enqueue(keyValue);
}
System.println(“Decoded Message:\n” + decoded);
}
}
程序在两个队列中保存了k值的两个副本。加密信息时用一个,解密信息时用另一个。因为解密时需要将信息的第一个字符对应到第一个k值。
程序中并没有环绕字母表。它将Unicode字符集中的字符移位到字符集的另一个位置来完成加密。所以我们可以对任何字符进行加密,包括大写字母、小写字母及标点符号或者空格都行。