1. Single machine job scheduling (n customers waiting for the same service)
Problem Description
Assuming that n customers are waiting for the same service at the same time, the service time required by customer i is t, 1<=i<=n, how to arrange the service order of n customers to minimize the total waiting time? The total waiting time is the sum of all customers waiting for service. Try to give a reason for your approach.
Use the greedy strategy to arrange the service time from small to large, and prioritize the shortest service time.
Proof (exchange argument)
2. Optimal prefix code- Huffman coding
definition
Binary prefix code: The 0,1 string that represents one character cannot be the prefix of the 0,1 string that represents another character.
B=∑f(xi)d(xi) is the average value of storing a character. d(xi) is the code length.
The prefix encoding scheme with the smallest average code length is called an optimal prefix encoding of character set C
Different characters |
a |
b |
c |
d |
e |
f |
Frequency f (thousand times) |
45 |
13 |
12 |
16 |
9 |
5 |
Fixed length code |
000 |
001 |
010 |
011 |
100 |
101 |
Variable length code |
0 |
101 |
100 |
111 |
1101 |
1100 |
Fake code
prove
C++ code
// 最优前缀码-Huffman编码
//二元前缀码:表示一个字符的0, 1字串不能是表示另一个字符的0, 1字串的前缀。
//B = ∑f(xi)d(xi)是存储一个字符的平均值。d(xi)为码长。
//平均码长达到最小的前缀编码方案称为字符集C的一个最优前缀编码。
//例:字符集及其频率如
//表.长为100000的文件:
//定长码:300000 bit,
//变长码:224000, 省25 %
// 算法:要点:编码字符均在叶子节点上,数据结构:队列中装树的结点,队列递增排序,取最小元素赋值给树节点左边右边,插入新节点后仍然递增,注意频率
//算法复杂度:
//2行排序O(nlogn)
//3行循环n - 1次
//8行循环体内插入操作
//O(logn),其它操作常量
//所以T(n) = O(nlogn)
// 关键词:贪心
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue> // 使用队列
#include<cstring>
#include <string>
using namespace std;
struct Huffman { // 存字符及其对应的频率 结构
string character; // 编码字符
float frequency;
};
struct Node { // 树结点结构
Huffman data;
Node* lChild;
Node* rChild;
Node(Huffman data)
{
this->data = data;
this->lChild = NULL;
this->rChild = NULL;
}
};
class MinHeap {//最小堆 min堆的实现 参考 https://blog.csdn.net/u010900754/article/details/54804303
private:
int size = 0;
vector<Huffman> heap;
public:
int getSize() {
return heap.size();
}
Huffman getElement(int i) {
return heap[i];
}
void add(Huffman &data) { // 添加一个元素,需要插在哪里的问题
heap.push_back(data);
int i = heap.size() - 1;
while (i > 0 && heap[i].frequency < heap[(i - 1) / 2].frequency) { //比较的是频率大小
swap(i, (i - 1) / 2);
i = (i - 1) / 2;
}
}
Huffman top() { //取走root结点,也需要调整堆中结点的位置
/*size--;*/
Huffman r = heap[0];
//swap(heap.size()-1, 0); // 交换是个什么操作??
vector<Huffman> T;
T.insert(T.begin(), heap.begin()+1, heap.end());
heap = T;
minheapify(0);
return r;
}
void minheapify(int i) {
int l = 2 * i + 1;
int r = 2 * i + 2;
int small = i;
if (l < heap.size() && heap[i].frequency > heap[l].frequency) {
small = l;
}
if (r < heap.size() && heap[r].frequency < heap[small].frequency) {
small = r;
}
if (i != small) {
swap(i, small);
minheapify(small);
}
}
void swap(int i, int j) {
Huffman temp = heap[i];
heap[i] = heap[j];
heap[j] = temp;
}
};
class Ques20201017
{
public:
void test(vector<string>& characters, vector<float>& frequencys) {
vector<Huffman> huffmans=init(characters, frequencys);
// 将数组中的元素进行排序,还是直接在一开始就赋值给队列?==>维护最小堆
MinHeap minheap = MinHeap();
for (int i = 0; i < characters.size(); i++) {
minheap.add(huffmans[i]);
}
//huffmans = minheap.getElement();// 得到排好序的数组
// 开辟叶结点
vector<Node*> que;
while(minheap.getSize()!=1) {
Huffman h1 = minheap.getElement(0);// 得到最小元素
Node* node1 = new Node(h1);
que.push_back(node1);
minheap.top();
Huffman h2 = minheap.getElement(0);// 得到第2小元素
Node* node2 = new Node(h2);
que.push_back(node2);
minheap.top();// 放入队列后就可以删除了
float fx = h1.frequency;
float fy = h2.frequency;
float fz = fx + fy;
// 新的第3个节点
Huffman temp;
temp.frequency = fz; // 无字符
temp.character = "O";
Node* mergeNode = new Node(temp);
minheap.add(temp); // 将第3个新增加的也添加进最小堆排序
mergeNode->lChild = node1;
mergeNode->rChild = node2;
}
Huffman last = minheap.getElement(0);// 得到最小元素
Node* lastnode = new Node(last);
que.push_back(lastnode);
// 打印结果
for (int i = que.size()-1; i >=0 ;i--) {
cout << " " << que[i]->data.character;
cout << endl;
}
}
private:
vector<Huffman> init(vector<string> &characters, vector<float> &frequencys) {
vector<Huffman> huffs;
for (int i = 0; i < characters.size();i++) {
Huffman h = Huffman();
h.character = characters[i];
h.frequency = frequencys[i];
huffs.push_back(h);
}
return huffs;
}
};
int main() {
Ques20201017 ques = Ques20201017();
vector<string> s = {"a","b","c", "d", "e","f"};
vector<float> freq = {45,13,12,16,9,5 };
ques.test(s, freq);
return 0;
}
running result
It seems that there are still some imperfections, such as how to traverse this tree. If there are too many homework, let's not do it first ==