泛型桥牌发牌应用--随机队列
算法第四版习题1.3.35~1.3.36
编写一个随机队列RandomQueue类来实现以下API:
RandomQueue() 创建一条空的随机队列
boolean isEmpty() 队列是否为空
void enqueue(Item item) 添加一个元素
Item dequeue() 删除并随机返回一个元素(取样且不放回)
Item sample() 随机返回一个元素但不删除它(取样且放回)
删除一个元素时,随机交换某个元素(索引在0和N-1之间)和末位元素(索引为N-1),然后删除并返回末位元素。编写一个桥牌用例。
另为上面的类编写一个迭代器,随机返回队列中的所有元素。
随机队列类:
package com.lch.Chapter1_3; import edu.princeton.cs.algs4.StdOut; import edu.princeton.cs.algs4.StdRandom; /** * * @author Lucas.Li * * @param <Item> */ public class RandomQueue<Item> { private int N; private Item[] array; @SuppressWarnings("unchecked") /** * 初始化数组array,大小为1 */ public RandomQueue() { array = (Item[]) new Object[1]; } /** * * @return 队列是否为空 */ public boolean isEmpty() { return N == 0; } /** * * @return 队列大小 */ public int size() { return N; } @SuppressWarnings("unchecked") /** * 调整数组大小 * @param max */ public void resize(int max) { Item[] temp = (Item[]) new Object[max]; for (int i = 0; i < N; i++) { temp[i] = array[i]; } array = temp; } /** * 为队列添加元素 * @param item */ public void enqueue(Item item) { if (N == array.length) { resize(N * 2); } array[N++] = item; } /** * * @return 随机交换后的末位元素 */ public Item dequeue() { if (N == 0) { try { throw new Exception("There is none in array."); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } if (N == (array.length / 4)) { resize(array.length / 2); } if (N == 1) { Item item = array[0]; array[0] = null; return item; } else { int randomIndex = StdRandom.uniform(0, N - 1); Item temp = array[randomIndex]; array[randomIndex] = array[N - 1]; array[N - 1] = null; N--; return temp; } } /** * * @return 随机元素 */ public Item sample() { Item item = array[StdRandom.uniform(N)]; return item; } @SuppressWarnings("unchecked") /** * 迭代器:随机返回所有元素 */ public void randomIterator() { int M = N; Item[] temp = array; Item[] store = (Item[]) new Object[M]; int m = 0; while (M > 1) { int random = StdRandom.uniform(M); Item tmp = temp[random]; temp[random] = temp[M - 1]; store[m] = tmp; M--; m++; } store[m] = temp[0]; for (int i = 0; i < store.length; i++) { StdOut.print(store[i] + " "); if ((i + 1) % 13 == 0) { StdOut.println(); } } } /** * 迭代器:按索引返回所有元素 */ public void iterator() { for (int i = 0; i < N; i++) { StdOut.print(array[i] + " "); } StdOut.println(); } }
桥牌方法:
/** * * @param 牌面 */ public static void showCards(String[] cards) { for (int i = 0; i < cards.length; i++) { StdOut.print(cards[i] + " "); } StdOut.println(); } /** * * @return 52张牌 */ public static String[] playingCards() { String[] cards = new String[52]; for (int i = 1; i < 10; i++) { cards[i * 4 - 4] = "heart" + (i + 1); cards[i * 4 - 3] = "spade" + (i + 1); cards[i * 4 - 2] = "club" + (i + 1); cards[i * 4 - 1] = "diamond" + (i + 1); } cards[36] = "heartJ"; cards[37] = "spadeJ"; cards[38] = "clubJ"; cards[39] = "diamondJ"; cards[40] = "heartQ"; cards[41] = "spadeQ"; cards[42] = "clubQ"; cards[43] = "diamondQ"; cards[44] = "heartK"; cards[45] = "spadeK"; cards[46] = "clubK"; cards[47] = "diamondK"; cards[48] = "heartA"; cards[49] = "spadeA"; cards[50] = "clubA"; cards[51] = "diamondA"; return cards; }
测试方法:
/** * 桥牌发牌 */ public static void p035() { String[] cards = playingCards(); String[] player1 = new String[13]; String[] player2 = new String[13]; String[] player3 = new String[13]; String[] player4 = new String[13]; RandomQueue<String> randomQueue = new RandomQueue<String>(); for (int i = 0; i < cards.length; i++) { randomQueue.enqueue(cards[i]); } for (int i = 0; i < 13; i++) { player1[i] = randomQueue.dequeue(); player2[i] = randomQueue.dequeue(); player3[i] = randomQueue.dequeue(); player4[i] = randomQueue.dequeue(); } StdOut.print("Player1's cards : "); showCards(player1); StdOut.print("Player2's cards : "); showCards(player2); StdOut.print("Player3's cards : "); showCards(player3); StdOut.print("Player4's cards : "); showCards(player4); }