《Java数据结构和算法》第二版 Robert lafore 编程作业 第八章

《Java数据结构和算法》第二版 Robert lafore  编程作业 第八章

/*
 	编程作业 
 	8.1	从tree.java程序(清单8.1)出发,把它修改成用用户输入的字母的
 		字符串建立二叉树(如A、B等等),每个字母在各自的节点中显示。
 		建立树,让每个包含字母的节点是叶节点。父节点可以有非字母标志
 		如'+'。保证每个父节点都恰好有两个子节点。不要担心树不平衡。
 		注意这不是搜索树;没有快速的方法来查找节点。最后结果可以像下
 		面所示的一样:
 		                       +                                                              
                     +                              E                              
        	  +              D              --              --              
    	  +      C      --      --      --      --      --      --      
  		A  B  --  --  --  --  --  --  --  --  --  --  --  --  --  --
  		一种方法是建立一个树的数组。(一组没有连接的树称为森林。)用
  		用户输入的每个字母作为一个节点。把每个节点作为一棵树,节点就
  		是根。现在把这些单节点的树放到数组中。下面开始建立一棵以'+'
  		为根的树,两个单节点树为它的子节点。依次把数组中的单节点树加
  		到这棵大点的树中。不要担心它是不是平衡树。实际可以用生成的中
  		间树覆盖数组单元,该数组单元的内容已经加到树中。find()、
  		insert()和delete()例程只用于搜索树,可以删掉了。保留
  		displayTree()方法和遍历方法,它们对所有二叉树都通用。
  	8.2	 扩展编程作业8.1中的功能来创建平衡树。一种方法是保证节点尽可
  		能出现在最底层。开始把每对单节点树建成三节点树,以'+'为根。
  		这样就有一个三节点树的森林了。合并每对三节点树变成七点节点树
  		的森林。随着每棵树节点数目的增加,树的数量减少,直到最后只有
  		一棵树。
  	8.3	还是从tree.java程序开始。根据用户输入的字符创建树。这次,建
  		立完全树--除了底层的最右边可能为空,其它层节点完全满的树。字
  		母要从上到下以及从左到右有序,好像就是建立了一个字符的金字塔。
  		(这种排列方法与本章前面讨论的三种遍历方法都不对应。)因此,
  		字符串ABCDEFGHIJ会排列成下面的样子:
			                       A                                                              
		            B                              C                              
		    D              E              F              G              
		H      I      J      --      --      --      --      --   
		建立这种树的一种方法是从上到下,而不是像编程作业中前两题那样
		从底向上。从建立一个作为最后树的根的节点开始。如果节点编号和
		字母排顺序一样,1是根,则编号为n的节点的左子节点的编号为2*n+1。
		可以用递归方法,创建两个了节点并在每个子节点中调用它自己的。
		节点创建的顺序不需要和它们插入到树中的顺序相同。像编程作业中
		前面的题那样,可以删掉Tree类中搜索树的一些方法。
  	8.4	编写程序根据后缀表达式建立树,如本章图8.11中所示。需要修改
  		tree.java程序(清单8.1)中的Tree类,和第4单postfix.java程序
  		(清单4.8)中的ParsePost类。更多细节参考图8.11的解。建好树之后,
  		遍历树可以得到算术表达式相应的前缀、中缀和后缀表达式。中缀表达
  		式需要小括号来避免产生模糊不清的表达式。InOrder()方法中,在第
  		一次递归调用之前加入左括号,在第二次递归调用之后加入右括号。
  	8.5	编写程序实现哈夫曼编码和解码。需要做如下的工作:
  		Accept a text message,possibly of more than one line.
  		Create a Huffman tree for this message.
  		Create a code table.
  		Encode the message into binary.
  		Decode the message from binary back to text.
  		如果信息很短,程序可以显示建立好的哈夫曼树。编程作业8.1、8.2
  		和8.3的方法会有所帮助的。可以用String变量把二进制数存储为字
  		符1和0的序列。除非确有必要,否则不需要做实际的位处理。
 */
package chap08;

// tree.java
// demonstrates binary tree
// to run this program: C>java TreeApp
import java.io.*;
import java.util.*;               // for Stack class


class Node {
	public char cchar;
	public Node leftChild;         // this node's left child
	public Node rightChild;        // this node's right child

	public Node() {
	}

	public Node(char c) {
		cchar = c;
	}

	public void displayNode()      // display ourself
	{
		System.out.print('{');
		System.out.print(cchar);
		System.out.print("} ");
	}
}  // end class Node
// //

class Tree implements Comparable {
	// 改成了public
	public Node root;             // first node of tree
	public int weight; // 权重

	// -------------------------------------------------------------
	public Tree()                  // constructor
	{
		root = null;
	}            // no nodes in tree yet

	// 添加了toString()方法
	public String toString() {
		return root.cchar + "";
	}

	// -------------------------------------------------------------
	public void traverse(int traverseType) {
		switch (traverseType) {
		case 1:
			System.out.print("\nPreorder traversal: ");
			preOrder(root);
			break;
		case 2:
			System.out.print("\nInorder traversal:  ");
			inOrder(root);
			break;
		case 3:
			System.out.print("\nPostorder traversal: ");
			postOrder(root);
			break;
		}
		System.out.println();
	}

	// -------------------------------------------------------------
	private void preOrder(Node localRoot) {
		if (localRoot != null) {
			System.out.print(localRoot.cchar + " ");
			preOrder(localRoot.leftChild);
			preOrder(localRoot.rightChild);
		}
	}

	// -------------------------------------------------------------
	private void inOrder(Node localRoot) {
		if (localRoot != null) {
			System.out.print("(");
			inOrder(localRoot.leftChild);
			System.out.print(localRoot.cchar + " ");
			inOrder(localRoot.rightChild);
			System.out.print(")");
		}
	}

	// -------------------------------------------------------------
	private void postOrder(Node localRoot) {
		if (localRoot != null) {
			postOrder(localRoot.leftChild);
			postOrder(localRoot.rightChild);
			System.out.print(localRoot.cchar + " ");
		}
	}

	// -------------------------------------------------------------
	public void displayTree() {
		Stack globalStack = new Stack();
		globalStack.push(root);
		int nBlanks = 32;
		boolean isRowEmpty = false;
		System.out
				.println("......................................................");
		while (isRowEmpty == false) {
			Stack localStack = new Stack();
			isRowEmpty = true;

			for (int j = 0; j < nBlanks; j++)
				System.out.print(' ');

			while (globalStack.isEmpty() == false) {
				Node temp = (Node) globalStack.pop();
				if (temp != null) {
					System.out.print(temp.cchar);
					localStack.push(temp.leftChild);
					localStack.push(temp.rightChild);

					if (temp.leftChild != null || temp.rightChild != null)
						isRowEmpty = false;
				} else {
					System.out.print("--");
					localStack.push(null);
					localStack.push(null);
				}
				for (int j = 0; j < nBlanks * 2 - 2; j++)
					System.out.print(' ');
			}  // end while globalStack not empty
			System.out.println();
			nBlanks /= 2;
			while (localStack.isEmpty() == false)
				globalStack.push(localStack.pop());
		}  // end while isRowEmpty is false
		System.out
				.println("......................................................");
	}  // end displayTree()
		// -------------------------------------------------------------

	@Override
	public int compareTo(Object o) {
		if (o == null) {
			return -1;
		}
		return weight - ((Tree) o).weight;
	}
}  // end class Tree
// //

public class TreeApp {
	// 编程作业 8.1
	public static void code8_1() throws IOException {
		System.out.println("请输入至少字符串(至少两个字符):");
		String str = getString();
		Tree[] array = new Tree[str.length()];
		for (int i = 0; i < str.length(); i++) {// 建立单节点树数组
			Tree temp = new Tree();
			temp.root = new Node(str.charAt(i));
			array[i] = temp;
		}
		for (int i = 1; i < str.length(); i++) {
			Tree temp = new Tree();
			temp.root = new Node('+');
			temp.root.leftChild = array[i - 1].root;
			temp.root.rightChild = array[i].root;
			array[i] = temp;
		}
		Tree lastTree = array[str.length() - 1];
		lastTree.displayTree();
	}

	// 编程作业 8.2
	// 这是按题目8.2要求来的平衡二叉树
	public static void code8_2() throws IOException {
		System.out.println("请输入至少字符串(至少两个字符):");
		String str = getString();
		Tree[] array = new Tree[str.length()];
		for (int i = 0; i < array.length; i++) {// 建立单节点树数组
			Tree temp = new Tree();
			temp.root = new Node(str.charAt(i));
			array[i] = temp;
		}

		Tree[] tempArray;
		while (array.length > 1) {
			tempArray = new Tree[(array.length - 1) / 2 + 1];
			int j = -1;
			int i = 0;
			for (; i + 1 < array.length; i += 2) {
				Tree temp = new Tree();
				temp.root = new Node('+');
				temp.root.leftChild = array[i].root;
				temp.root.rightChild = array[i + 1].root;
				tempArray[++j] = temp;
			}
			if (i < array.length) {
				Tree temp = new Tree();
				temp.root = new Node('+');
				temp.root.leftChild = array[array.length - 1].root;
				tempArray[++j] = temp;
				// tempArray[++j] = array[i];
			}
			array = tempArray;
		}
		Tree lastTree = array[array.length - 1];
		lastTree.displayTree();
	}

	// 编程作业 8.2
	// 这才是真正的平衡二叉树
	public static void code8_2_1() throws IOException {
		System.out.println("请输入至少字符串(至少两个字符):");
		String str = getString();
		Tree[] array = new Tree[str.length()];
		for (int i = 0; i < array.length; i++) {// 建立单节点树数组
			Tree temp = new Tree();
			temp.root = new Node(str.charAt(i));
			array[i] = temp;
		}

		Tree lastTree = connectTree(array, 0, array.length - 1);
		lastTree.displayTree();
	}

	private static Tree connectTree(Tree[] array, int left, int right) {
		if (left == right) {
			return array[left];
		} else {
			Tree tempTree = new Tree();
			tempTree.root = new Node('+');
			tempTree.root.leftChild = connectTree(array, left,
					(right + left) / 2).root;
			tempTree.root.rightChild = connectTree(array,
					(right + left) / 2 + 1, right).root;
			return tempTree;
		}
	}

	// 编程作业 8.3
	public static void code8_3() throws IOException {
		System.out.println("请输入至少字符串(至少两个字符):");
		String str = getString();
		Tree[] array = new Tree[str.length()];
		for (int i = 0; i < array.length; i++) {// 建立单节点树数组
			Tree temp = new Tree();
			temp.root = new Node(str.charAt(i));
			array[i] = temp;
		}
		Tree lastTree = connectTree1(array, 0);
		lastTree.displayTree();
	}

	private static Tree connectTree1(Tree[] array, int index) {
		if (index * 2 + 1 > array.length - 1) { // 没有子树
			return array[index];
		} else if (index * 2 + 2 > array.length - 1) { // 有左子树
			Tree temp = array[index];
			temp.root.leftChild = connectTree1(array, index * 2 + 1).root;
			return temp;
		} else { // 有左右子树
			Tree temp = array[index];
			temp.root.leftChild = connectTree1(array, index * 2 + 1).root;
			temp.root.rightChild = connectTree1(array, index * 2 + 2).root;
			return temp;
		}
	}

	public static void main(String[] args) throws IOException {
		// 编程作业 8.1 - 8.3
		// code8_1();
		// code8_2();
		// code8_2_1();
		code8_3();
	}  // end main()

	// -------------------------------------------------------------

	public static String getString() throws IOException {
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		String s = br.readLine();
		return s;
	}

	// -------------------------------------------------------------
	public static char getChar() throws IOException {
		String s = getString();
		return s.charAt(0);
	}

	// -------------------------------------------------------------
	public static int getInt() throws IOException {
		String s = getString();
		return Integer.parseInt(s);
	}
	// -------------------------------------------------------------
}  // end class TreeApp
// //


 

package chap08;

// postfix.java
// parses postfix arithmetic expressions
// to run this program: C>java PostfixApp
import java.io.*;              // for I/O


class StackX {
	private int maxSize;
	private Tree[] stackArray;
	private int top;

	// --------------------------------------------------------------
	public StackX(int size)      // constructor
	{
		maxSize = size;
		stackArray = new Tree[maxSize];
		top = -1;
	}

	// --------------------------------------------------------------
	public void push(Tree j)     // put item on top of stack
	{
		stackArray[++top] = j;
	}

	// --------------------------------------------------------------
	public Tree pop()            // take item from top of stack
	{
		return stackArray[top--];
	}

	// --------------------------------------------------------------
	public Tree peek()           // peek at top of stack
	{
		return stackArray[top];
	}

	// --------------------------------------------------------------
	public boolean isEmpty()    // true if stack is empty
	{
		return (top == -1);
	}

	// --------------------------------------------------------------
	public boolean isFull()     // true if stack is full
	{
		return (top == maxSize - 1);
	}

	// --------------------------------------------------------------
	public int size()           // return size
	{
		return top + 1;
	}

	// --------------------------------------------------------------
	public Tree peekN(int n)     // peek at index n
	{
		return stackArray[n];
	}

	// --------------------------------------------------------------
	public void displayStack(String s) {
		System.out.print(s);
		System.out.print("Stack (bottom-->top): ");
		for (int j = 0; j < size(); j++) {
			System.out.print(peekN(j));
			System.out.print(' ');
		}
		System.out.println("");
	}
	// --------------------------------------------------------------
}  // end class StackX
// //

class ParsePost {
	private StackX theStack;
	private String input;

	// --------------------------------------------------------------
	public ParsePost(String s) {
		input = s;
	}

	// --------------------------------------------------------------
	// 编程作业 8.4
	public Tree doParse() {
		theStack = new StackX(20);             // make new stack
		char ch;
		int j;
		Tree num1, num2, interAns;

		for (j = 0; j < input.length(); j++)       // for each char,
		{
			ch = input.charAt(j);              // read from input
			theStack.displayStack("" + ch + " ");  // *diagnostic*
			if (ch >= '0' && ch <= '9') {         // if it's a number
				Tree temp = new Tree();
				temp.root = new Node(ch);
				theStack.push(temp); // push it
			} else                               // it's an operator
			{
				num2 = theStack.pop();          // pop operands
				num1 = theStack.pop();
				Tree temp;
				switch (ch)                      // do arithmetic
				{
				case '+':
					temp = new Tree();
					temp.root = new Node('+');
					temp.root.leftChild = num1.root;
					temp.root.rightChild = num2.root;
					theStack.push(temp);
					break;
				case '-':
					temp = new Tree();
					temp.root = new Node('-');
					temp.root.leftChild = num1.root;
					temp.root.rightChild = num2.root;
					theStack.push(temp);
					break;
				case '*':
					temp = new Tree();
					temp.root = new Node('*');
					temp.root.leftChild = num1.root;
					temp.root.rightChild = num2.root;
					theStack.push(temp);
					break;
				case '/':
					temp = new Tree();
					temp.root = new Node('/');
					temp.root.leftChild = num1.root;
					temp.root.rightChild = num2.root;
					theStack.push(temp);
					break;
				default:
					// interAns = 0;
				}  // end switch
					// theStack.push(interAns); // push result
			}  // end else
		}  // end for
		interAns = theStack.pop();            // get answer
		return interAns;
	}  // end doParse()
}  // end class ParsePost
// //

public class PostfixApp {
	public static void main(String[] args) throws IOException {
		String input;
		Tree output;

		System.out.print("Enter postfix: ");
		System.out.flush();
		input = getString();         // read a string from kbd
		if (input.equals(""))       // quit if [Enter]
			return;
		// make a parser
		ParsePost aParser = new ParsePost(input);
		output = aParser.doParse();  // do the evaluation
		// System.out.println("Evaluates to " + output);
		output.displayTree();
		output.traverse(1);
		output.traverse(2);
		output.traverse(3);
	}  // end main()
		// --------------------------------------------------------------

	public static String getString() throws IOException {
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		String s = br.readLine();
		return s;
	}
	// --------------------------------------------------------------
}  // end class PostfixApp
// //


 

package chap08;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.TreeMap;

// =============================================================================
// 编程作业 8.5
public class Huffman {
	public static Map<Character, String> map_char_code;
	public static Map<String, Character> map_code_char;
	static {
		map_char_code = new HashMap<Character, String>(); // 编码用代码表
		map_code_char = new HashMap<String, Character>(); // 解码用代码表
	}

	// 编码分为四步
	// 1.统计字符频率
	// 2.生成Huffman树
	// 3.生成编解码用代码表
	// 4.编码字符串
	public static String encode(String str) {
		char[] cchar = str.toCharArray();

		// 1.统计字符频率
		TreeMap<Character, Integer> map = new TreeMap<Character, Integer>();
		for (int i = 0; i < cchar.length; i++) {
			if (map.containsKey(cchar[i])) {
				map.put(cchar[i], map.get(cchar[i]).intValue() + 1);
			} else {
				map.put(cchar[i], 1);
			}
		}

		// 2.生成Huffman树
		// 先由所有字符生成单节点树的森林
		// 然后根据优先级合成单节点树为一棵树
		Queue<Tree> forest = new PriorityQueue<Tree>();
		Set<Map.Entry<Character, Integer>> set = map.entrySet();
		Iterator<Map.Entry<Character, Integer>> it = set.iterator();
		while (it.hasNext()) { // 生成单节点树
			Map.Entry<Character, Integer> en = it.next();
			Tree temp = new Tree();
			temp.root = new Node(en.getKey());
			temp.weight = en.getValue();
			forest.add(temp);
		}
		while (forest.size() > 1) { // 把单节点树合并为一棵树立
			Tree t1 = forest.remove();
			Tree t2 = forest.remove();
			Tree t3 = new Tree();
			t3.root = new Node();
			t3.weight = t1.weight + t2.weight;
			t3.root.leftChild = t1.root;
			t3.root.rightChild = t2.root;
			forest.add(t3);
		}
		Tree t = forest.remove(); // 最后一棵树

		// 3.生成编解码用map
		String code = "";
		preOrder(t.root, code, map_char_code, map_code_char);

		// 4.编码字符串
		StringBuffer output = new StringBuffer();
		for (int i = 0; i < cchar.length; i++) {
			output.append(map_char_code.get(cchar[i]));
		}
		return output.toString();
	}

	// 遍历Huffman树生成编解码代码表
	private static void preOrder(Node localRoot, String code,
			Map<Character, String> map_char_code,
			Map<String, Character> map_code_char) {
		if (localRoot != null) {
			if (localRoot.cchar != '\0') {
				map_char_code.put(localRoot.cchar, code);
				map_code_char.put(code, localRoot.cchar);
			}
			preOrder(localRoot.leftChild, code + "0", map_char_code,
					map_code_char);
			preOrder(localRoot.rightChild, code + "1", map_char_code,
					map_code_char);
		}
	}

	// 解码
	// 根据确码代码表还原信息
	public static String decode(String str) {
		StringBuffer result = new StringBuffer();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < str.length(); i++) {
			sb.append(str.charAt(i));
			if (map_code_char.get(sb.toString()) != null) {
				result.append(map_code_char.get(sb.toString()));
				sb = new StringBuffer();
			}
		}
		return result.toString();
	}

	public static void main(String[] args) {
		String code = encode("SUSIE SAYS IT IS EASY!");
		System.out.println(code);
		String str = decode(code);
		System.out.println(str);
	}

	// -------------------------------------------------------------

	public static String getString() throws IOException {
		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		String s = br.readLine();
		return s;
	}
}
// =============================================================================


 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值