1. 程式人生 > >演算法導論 練習題 16.3-7

演算法導論 練習題 16.3-7

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 6
typedef struct Huff
{
	int freq;
	Huff *left;
	Huff *middle;
	Huff *right;
	char c;
}HuffNode,*pHuff;

typedef struct 
{
	int len;
	pHuff *arr;
}MinHeap;

void swop(pHuff *a,pHuff *b)
{
	pHuff temp=*a;
	*a=*b;
	*b=temp;
}

void minHeapify(pHuff *a,int len,int i)
{
	if(len<=0)
		return;
	int l=i*2,r=i*2+1,min=a[i]->freq,p=i;
	if(l<len && a[l]->freq<a[i]->freq)
	{
		min=a[l]->freq;
		p=l;
	}
	if(r<len && a[r]->freq<min)
	{
		min=a[r]->freq;
		p=r;
	}
	if(p!=i)
	{
		swop(&a[i],&a[p]);
		minHeapify(a,len,p);
	}
}

MinHeap* buildHeap(int *a,int len,char *cs)
{
	MinHeap *m=(MinHeap *)malloc(sizeof(MinHeap));
	m->arr=(pHuff*)malloc(len*sizeof(pHuff));
	m->len=len;
	for(int i=0;i<len;i++)
	{
		m->arr[i]=(pHuff)malloc(sizeof(Huff));
		m->arr[i]->freq=a[i];
		m->arr[i]->c=cs[i];
		m->arr[i]->left=m->arr[i]->right=m->arr[i]->middle=NULL;
	}
	for(int i=(len+1)/2;i>=0;i--)
	{
		minHeapify(m->arr,m->len,i);
	}
	return m;
}

void printHeap(MinHeap *heap)
{
	for(int i=0;i<heap->len;i++)
	{
		printf("%d ",heap->arr[i]->freq);
	}
	printf("\n");
}

pHuff extractMin(MinHeap *heap)
{
	if(heap->len<=0)
		return NULL;
	pHuff x=heap->arr[0];
	swop(&heap->arr[0],&heap->arr[heap->len-1]);
	heap->len--;
	minHeapify(heap->arr,heap->len,0);
	return x;
}

void insert(MinHeap *heap,pHuff h)
{
	heap->arr[heap->len++]=h;
	int i=heap->len-1;
	int x=i/2;
	while(x>0)
	{
		if(heap->arr[i]->freq<heap->arr[x]->freq)
		{
			swop(&heap->arr[i],&heap->arr[x]);
			i=x;
			x=x/2;
		}
		else
			break;
	}
	if(x==0 && heap->arr[i]->freq<heap->arr[x]->freq)
	{
		swop(&heap->arr[i],&heap->arr[x]);
	}
}

pHuff makeNode(int freq,pHuff l,pHuff m,pHuff r)
{
	pHuff ph=(pHuff)malloc(sizeof(Huff));
	ph->freq=freq;
	ph->left=l;
	ph->right=r;
	ph->middle=m;
	ph->c='*';
	return ph;
}

pHuff huffman(int *a,int len,char*cs)
{
	MinHeap*m=buildHeap(a,len,cs);
	//printHeap(m);
	for(int i=1;m->len>1;i++)
	{
		if(i==1)
		{
			int k=N;
			while(k-2>=0)
			{
				k-=2;
			}
			if(k==0)
			{
				k=2;
			}
			else if(k==1)
			{
				k=3;
			}
			if(k==1)
			{
				pHuff x=extractMin(m);
				pHuff z=makeNode(x->freq,x,NULL,NULL);
				insert(m,z);
			}
			else if(k==2)
			{
				pHuff x=extractMin(m);
				pHuff y=extractMin(m);
				pHuff z=makeNode(x->freq+y->freq,x,y,NULL);
				insert(m,z);
			}
			else if(k==3)
			{
				pHuff x=extractMin(m);
				pHuff y=extractMin(m);
				pHuff w=extractMin(m);
				pHuff z=makeNode(x->freq+y->freq+w->freq,x,y,w);
				insert(m,z);
			}
		}
		else
		{
			pHuff x=extractMin(m);
			pHuff y=extractMin(m);
			pHuff w=extractMin(m);
			pHuff z=makeNode(x->freq+y->freq+w->freq,x,y,w);
			insert(m,z);
		}	
	}
	return m->arr[0];
}

void getCode(pHuff ph,char *s,char c,int i)
{
	if(ph==NULL)
		return;
	if(c==ph->c)
	{
		s[i]='\0';
		printf("%s",s);
		return;
	}
	s[i]='0';
	getCode(ph->left,s,c,i+1);
	s[i]='1';
	getCode(ph->middle,s,c,i+1);
	s[i]='2';
	getCode(ph->right,s,c,i+1);
}

void printHuff(pHuff ph)
{
	if(ph==NULL)
		return;
	printf("%c ",ph->c);
	printHuff(ph->left);
	printHuff(ph->middle);
	printHuff(ph->right);
}

void  main()
{
	int a[N]={45,13,12,16,9,5};
	char cs[N]={'a','b','c','d','e','f'};
	pHuff ph=huffman(a,N,cs);
	char*s=(char*)malloc((N+1)*sizeof(char));
	//printHuff(ph);
	getCode(ph,s,'e',0);
	getchar();
}

相關推薦

演算法導論 練習題 16.3-7

#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 6 typedef struct Huff { int freq; Huff *left; H

二叉搜尋樹增刪節點《演算法導論》12.3

向二叉搜尋樹增加一個節點是比較簡單的,每個新節點都會成為樹上的新葉子,我們要做的是從根開始,沿著一條路徑,抵達安放新葉子的正確位置。這條路徑是怎樣找到的呢? 路徑的起點自然是根節點了,把起點作為當前節點,和新節點比較大小,如果新節點較小,那麼新節點應該屬於當前節點的左子樹,於是選擇當前節點的左孩子作為新

演算法導論》12.3節習題

12.3-1 二叉搜尋樹insert操作的遞迴版本 void insert1(Node* pRoot, Node* pAdd) { bool bLeft = pAdd->key < pRoot->key; Node* pNextRoot = bLeft ? pRo

演算法導論2.1.3

#include<iostream> using namespace std; int main() {     int j;     int aim = 10;     int  quene[10] = { 9,4,7,1,8,3,6,2,5,0 };   

演算法導論(第3版)》讀書筆記(一)演算法基礎

本篇內容主要涉及《演算法導論》一書中的第二章知識,涉及的內容有插入排序和歸併排序 插入排序 對於插入排序有個很明顯的顯示生活例子來幫助我們理解,插入排序的工作原理就像打撲克牌一樣,右手從桌面上拿起一張牌,然後再左手那一堆已經按牌面大小排好序的牌找

演算法導論 思考題 4-3

a. 利用主方法可得,T(n)=θ(n的log34次方) b. n/f(n)=lgn,不能應用主方法     共log3n+1層,每層代價n/lgn/(3的i次方),最後一層共n個θ(1)的結點,代價為θ(n)     T(n)=∑n/lgn/(3的i次方)+θ(n)  

演算法導論》第3版 第2章課後題答案(英文版)

Solution to Exercise 2.2-2    SELECTION-SORT(A)    n = A.length    for j = 1 to n - 1        smallest = j        for i = j + 1 to n       

演算法導論答案 16.2-4

//16.2-4 #include <iostream> using namespace std; #define N 6 int x[N+1]={0,10,40,60,90,120,140},f[N+1]={0};//f用於標記某一站是否加油,x[i]表示第

演算法導論複習(3) 堆排序

堆排序與歸併排序具有相同的時間複雜度O(nlgn),但是在講堆排序之前,先要搞清楚堆排序使用的“二叉堆” 二叉堆是一個數組,可以被看成近似的完全二叉樹 特點: 1.樹上每一節點對應一個

演算法導論 練習 2.3-6

題目: 是否可以用二分查詢法把插入排序最壞條件下執行時間改善到 Θ(nlgn)? 解答: 顯然是不可以的,陣列排序中影響時間複雜度的因素有兩個,一個是尋找位置時的比較,一個是找到位置後插入操作

演算法導論 練習 2.3-1

題目: 說明合併排序在陣列A={3,41,52,26,38,57,9,49} 上的執行過程 解答: 原陣列:3,41,52,26,38,57,9,49 第一趟:3,41,26,52,38,57

演算法導論 5.2-3

令X為一個隨機變數,其值等於擲n次骰子點數的綜合。令Xij對應於第i次擲骰子得到的點數是j這個事件的指示器隨機變數。所以Xij = I{第i次擲骰子得到的點數是j},並且X=∑i=1n ∑j=16 jXij 。 E(X)=E(∑i=1n ∑j=16 jXij ) = E(∑j=16 jX1j +∑j=16

演算法導論 5.1-3

畫出BIASED-RANDOM真值表 輸出值 0 1 概率 1-p p 基於BIASE-RANDOM真值表,畫出獨立的兩次BIASED-RANDOM過程的真值表 輸出值 00 01 10 11 概率 (1-p)(1-p) p(1-p) p(1-p) pp 可見輸出01和10的概率是相同的,那麼可以使用如

演算法導論之2-3思考題

題目:霍納規則的正確性: 寫出虛擬碼以實現樸素多項式求值(native polynomial-evaluation)演算法,它從頭開 始計算多項式的每一個項。這個演算法的執行時間是多少?與霍納規則相比其效能如何? 我用Java程式碼將其

(演算法導論習題解exercise2.3-7)給定一個整數序列以及一個數X,確定該序列中是否有兩個數的和為X

這是<<演算法導論>>中的一題,exercise 2.3-7.可以這麼做:1) 首先將序列排序,去掉重複的元素.2) 其次生成一個序列, 該序列中每個元素都是X-原序列中的值, 同樣的,去重.3) 對這兩個已經排序好的序列進行合併操作.4) 如果有兩個元素之和為X, 那麼在合併

演算法導論3.1練習題

3.1-1: 假設0⩽c1(f(n)+g(n))⩽max(f(n),g(n))⩽c2(f(n)+g(n)) ∴0⩽c1(x+y)⩽x+y+|x−y|2⩽c2(x+y)

算法導論2.3-7

clu mit body sort 相加 2.3 not pan ret 問題:請給出一個運行時間為O(n lgn)的算法,使之能在給定一個由n個整數構成的集合S和另一個整數x時, 判斷S中是否存在有兩個其和等於x的元素。 題目思路:先將集合S用歸並排序排好序,因為歸並

用正則表達式實現 運算 express = '1 -2* ((60-30 +(-40/5) *(9-2*5/3 +7 /3*99 /4*2998 +10 *568 /14))-(-4*3)/(16-3*2))'

repl bsp val 實現 strip expr 運算 lac spl #!/usr/bin/env python # coding:utf-8 import re def dealwith(express): express.replace(‘+-‘,‘

#006# 快速排序 × 演算法導論(第三版)練習 7.1-1 ~ 7.1-4

快排採用經典的分治思想,具體如下↓ 分解:快排的核心步驟,其結果是陣列被分成以某個數為基準的左右兩個子陣列(可能為空),其中左邊的數都小於該基準數,右邊的數都大於該基準數。詳細步驟包括計算基準數下標,以及移動陣列內元素。 解決:通過遞迴呼叫快速排序,對兩個子陣列進行排序。 合併:因為是原址排序,快速排序

演算法導論(第三版)練習 10.1-1 ~ 10.1-7 兩個棧實現佇列 兩個佇列實現棧

棧與佇列js實現版本: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title>