Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package by.it.group351004.narivonchik.lesson03;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.util.*;
- //Lesson 3. A_Huffman.
- //Разработайте метод encode(File file) для кодирования строки (код Хаффмана)
- // По данным файла (непустой строке ss длины не более 104104),
- // состоящей из строчных букв латинского алфавита,
- // постройте оптимальный по суммарной длине беспрефиксный код.
- // Используйте Алгоритм Хаффмана — жадный алгоритм оптимального
- // безпрефиксного кодирования алфавита с минимальной избыточностью.
- // В первой строке выведите количество различных букв kk,
- // встречающихся в строке, и размер получившейся закодированной строки.
- // В следующих kk строках запишите коды букв в формате "letter: code".
- // В последней строке выведите закодированную строку. Примеры ниже
- // Sample Input 1:
- // a
- //
- // Sample Output 1:
- // 1 1
- // a: 0
- // 0
- // Sample Input 2:
- // abacabad
- //
- // Sample Output 2:
- // 4 14
- // a: 0
- // b: 10
- // c: 110
- // d: 111
- // 01001100100111
- public class A_Huffman {
- //Изучите классы Node InternalNode LeafNode
- abstract class Node implements Comparable<Node> {
- //абстрактный класс элемент дерева
- //(сделан abstract, чтобы нельзя было использовать его напрямую)
- //а только через его версии InternalNode и LeafNode
- private final int frequence; //частота символов
- //генерация кодов (вызывается на корневом узле
- //один раз в конце, т.е. после построения дерева)
- abstract void fillCodes(String code);
- //конструктор по умолчанию
- private Node(int frequence) {
- this.frequence = frequence;
- }
- //метод нужен для корректной работы узла в приоритетной очереди
- //или для сортировок
- @Override
- public int compareTo(Node o) {
- return Integer.compare(frequence, o.frequence);
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////
- //расширение базового класса до внутреннего узла дерева
- private class InternalNode extends Node {
- //внутренный узел дерева
- Node left; //левый ребенок бинарного дерева
- Node right; //правый ребенок бинарного дерева
- //для этого дерева не существует внутренних узлов без обоих детей
- //поэтому вот такого конструктора будет достаточно
- InternalNode(Node left, Node right) {
- super(left.frequence + right.frequence);
- this.left = left;
- this.right = right;
- }
- @Override
- void fillCodes(String code) {
- left.fillCodes(code + "0");
- right.fillCodes(code + "1");
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////
- //расширение базового класса до листа дерева
- private class LeafNode extends Node {
- //лист
- char symbol; //символы хранятся только в листах
- LeafNode(int frequence, char symbol) {
- super(frequence);
- this.symbol = symbol;
- }
- @Override
- void fillCodes(String code) {
- //добрались до листа, значит рекурсия закончена, код уже готов
- //и можно запомнить его в индексе для поиска кода по символу.
- codes.put(this.symbol, code);
- }
- }
- //индекс данных из листьев
- static private Map<Character, String> codes = new TreeMap<>();
- //!!!!!!!!!!!!!!!!!!!!!!!!! НАЧАЛО ЗАДАЧИ !!!!!!!!!!!!!!!!!!!!!!!!!
- String encode(File file) throws FileNotFoundException {
- //прочитаем строку для кодирования из тестового файла
- Scanner scanner = new Scanner(file);
- String s = scanner.next();
- //все комментарии от тестового решения были оставлены т.к. это задание A.
- //если они вам мешают их можно удалить
- Map<Character, Integer> count = new HashMap<>();
- //1. переберем все символы по очереди и рассчитаем их частоту в Map count
- //для каждого символа добавим 1 если его в карте еще нет или инкремент если есть.
- char c;
- for (int i = 0; i < s.length(); i++) {
- boolean isThisElement = false;
- for(Map.Entry<Character, Integer> entry: count.entrySet()) {
- c = entry.getKey();
- if (s.charAt(i) == c) {
- isThisElement = true;
- count.put(c, entry.getValue()+1);
- break;
- }
- }
- if (!isThisElement)
- count.put(s.charAt(i), 1);
- }
- //2. перенесем все символы в приоритетную очередь в виде листьев
- PriorityQueue<Node> priorityQueue = new PriorityQueue<>();
- for(Map.Entry<Character, Integer> entry: count.entrySet()) {
- Node symbol = new LeafNode (entry.getValue(), entry.getKey());
- priorityQueue.add(symbol);
- }
- //3. вынимая по два узла из очереди (для сборки родителя)
- //и возвращая этого родителя обратно в очередь
- //построим дерево кодирования Хаффмана.
- //У родителя частоты детей складываются.
- while (priorityQueue.size() > 1) {
- Node leftSymbol = priorityQueue.remove();
- Node rightSymbol = priorityQueue.remove();
- Node parentsSymbol = new InternalNode(leftSymbol, rightSymbol);
- priorityQueue.add(parentsSymbol);
- }
- //4. последний из родителей будет корнем этого дерева
- //это будет последний и единственный элемент оставшийся в очереди priorityQueue.
- StringBuilder sb = new StringBuilder();
- Node root = priorityQueue.remove();
- root.fillCodes("");
- for (int i = 0; i < s.length(); i++) {
- sb.append(codes.get(s.charAt(i)));
- }
- return sb.toString();
- //01001100100111
- //01001100100111
- }
- //!!!!!!!!!!!!!!!!!!!!!!!!! КОНЕЦ ЗАДАЧИ !!!!!!!!!!!!!!!!!!!!!!!!!
- public static void main(String[] args) throws FileNotFoundException {
- String root = System.getProperty("user.dir") + "/src/";
- File f = new File(root + "by/it/a_khmelev/lesson03/dataHuffman.txt");
- A_Huffman instance = new A_Huffman();
- long startTime = System.currentTimeMillis();
- String result = instance.encode(f);
- long finishTime = System.currentTimeMillis();
- System.out.printf("%d %d\n", codes.size(), result.length());
- for (Map.Entry<Character, String> entry : codes.entrySet()) {
- System.out.printf("%s: %s\n", entry.getKey(), entry.getValue());
- }
- System.out.println(result);
- }
- }
- package by.it.group351004.narivonchik.lesson03;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.util.Map;
- import java.util.Scanner;
- import java.util.TreeMap;
- // Lesson 3. B_Huffman.
- // Восстановите строку по её коду и беспрефиксному коду символов.
- // В первой строке входного файла заданы два целых числа
- // kk и ll через пробел — количество различных букв, встречающихся в строке,
- // и размер получившейся закодированной строки, соответственно.
- //
- // В следующих kk строках записаны коды букв в формате "letter: code".
- // Ни один код не является префиксом другого.
- // Буквы могут быть перечислены в любом порядке.
- // В качестве букв могут встречаться лишь строчные буквы латинского алфавита;
- // каждая из этих букв встречается в строке хотя бы один раз.
- // Наконец, в последней строке записана закодированная строка.
- // Исходная строка и коды всех букв непусты.
- // Заданный код таков, что закодированная строка имеет минимальный возможный размер.
- //
- // Sample Input 1:
- // 1 1
- // a: 0
- // 0
- // Sample Output 1:
- // a
- // Sample Input 2:
- // 4 14
- // a: 0
- // b: 10
- // c: 110
- // d: 111
- // 01001100100111
- // Sample Output 2:
- // abacabad
- public class B_Huffman {
- String decode(File file) throws FileNotFoundException {
- StringBuilder result=new StringBuilder();
- //прочитаем строку для кодирования из тестового файла
- Scanner scanner = new Scanner(file);
- Integer count = scanner.nextInt();
- Integer length = scanner.nextInt();
- scanner.nextLine();
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! НАЧАЛО ЗАДАЧИ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
- Map<String, Character> codes = new TreeMap<>();
- String str;
- char symbol;
- String code;
- for (int i = 0; i < count; i++){
- str = scanner.nextLine();
- symbol = str.charAt(0);
- code = str.substring(3);
- codes.put(code, symbol);
- }
- String encodedStr = scanner.nextLine();
- int nowIndex = 0;
- int startCodeIndex = 0;
- while (nowIndex < length){
- if (encodedStr.charAt(nowIndex) == '0'){
- result.append(codes.get(encodedStr.substring(startCodeIndex, nowIndex+1)));
- startCodeIndex = nowIndex+1;
- }
- nowIndex++;
- }
- if(encodedStr.charAt(nowIndex-1) != '0')
- result.append(codes.get(encodedStr.substring(startCodeIndex, nowIndex)));
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! КОНЕЦ ЗАДАЧИ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
- return result.toString(); //01001100100111
- }
- public static void main(String[] args) throws FileNotFoundException {
- String root = System.getProperty("user.dir") + "/src/";
- File f = new File(root + "by/it/a_khmelev/lesson03/encodeHuffman.txt");
- B_Huffman instance = new B_Huffman();
- String result = instance.decode(f);
- System.out.println(result);
- }
- }
- package by.it.group351004.narivonchik.lesson03;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.InputStream;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Scanner;
- // Lesson 3. C_Heap.
- // Задача: построить max-кучу = пирамиду = бинарное сбалансированное дерево на массиве.
- // ВАЖНО! НЕЛЬЗЯ ИСПОЛЬЗОВАТЬ НИКАКИЕ КОЛЛЕКЦИИ, КРОМЕ ARRAYLIST (его можно, но только для массива)
- // Проверка проводится по данным файла
- // Первая строка входа содержит число операций 1 ≤ n ≤ 100000.
- // Каждая из последующих nn строк задают операцию одного из следующих двух типов:
- // Insert x, где 0 ≤ x ≤ 1000000000 — целое число;
- // ExtractMax.
- // Первая операция добавляет число x в очередь с приоритетами,
- // вторая — извлекает максимальное число и выводит его.
- // Sample Input:
- // 6
- // Insert 200
- // Insert 10
- // ExtractMax
- // Insert 5
- // Insert 500
- // ExtractMax
- //
- // Sample Output:
- // 200
- // 500
- public class C_HeapMax {
- private class MaxHeap {
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! НАЧАЛО ЗАДАЧИ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
- //тут запишите ваше решение.
- //Будет мало? Ну тогда можете его собрать как Generic и/или использовать в варианте B
- private List<Long> heap = new ArrayList<>();
- int siftDown(int i) {
- while (i < (heap.size() - 1) / 2) {
- int left = 2 * i + 1;
- int right = 2 * i + 2;
- int max = left;
- if((right < heap.size()) && (heap.get(right) > heap.get(left)))
- max = right;
- if(i == max)
- break;
- swap(i, max);
- i = max;
- }
- return i;
- }
- int siftUp(int i) {
- while (heap.get(i) > heap.get((i - 1) / 2)){
- swap(i, (i - 1) / 2);
- i = (i - 1) / 2;
- }
- return i;
- }
- void insert(Long value) { //вставка
- heap.add(value);
- siftUp(heap.size() - 1);
- }
- Long extractMax() { //извлечение и удаление максимума
- Long result;
- result = heap.get(0);
- heap.remove(0);
- siftDown(0);
- return result;
- }
- private void swap(int i, int j){
- Long temp = heap.get(j);
- heap.set(j, heap.get(i));
- heap.set(i, temp);
- }
- //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! КОНЕЦ ЗАДАЧИ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
- }
- //эта процедура читает данные из файла, ее можно не менять.
- Long findMaxValue(InputStream stream) {
- Long maxValue=0L;
- MaxHeap heap = new MaxHeap();
- //прочитаем строку для кодирования из тестового файла
- Scanner scanner = new Scanner(stream);
- Integer count = scanner.nextInt();
- for (int i = 0; i < count; ) {
- String s = scanner.nextLine();
- if (s.equalsIgnoreCase("extractMax")) {
- Long res=heap.extractMax();
- if (res!=null && res>maxValue) maxValue=res;
- System.out.println();
- i++;
- }
- if (s.contains(" ")) {
- String[] p = s.split(" ");
- if (p[0].equalsIgnoreCase("insert"))
- heap.insert(Long.parseLong(p[1]));
- i++;
- //System.out.println(heap); //debug
- }
- }
- return maxValue;
- }
- public static void main(String[] args) throws FileNotFoundException {
- String root = System.getProperty("user.dir") + "/src/";
- InputStream stream = new FileInputStream(root + "by/it/a_khmelev/lesson03/heapData.txt");
- C_HeapMax instance = new C_HeapMax();
- System.out.println("MAX="+instance.findMaxValue(stream));
- }
- // РЕМАРКА. Это задание исключительно учебное.
- // Свои собственные кучи нужны довольно редко.
- // "В реальном бою" все существенно иначе. Изучите и используйте коллекции
- // TreeSet, TreeMap, PriorityQueue и т.д. с нужным CompareTo() для объекта внутри.
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement