课程给出代码
C语言描述:堆的描述和操作
typedef struct HNode *Heap; /* 堆的类型定义 */
struct HNode {
ElementType *Data; /* 存储元素的数组 */
int Size; /* 堆中当前元素个数 */
int Capacity; /* 堆的最大容量 */
};
typedef Heap MaxHeap; /* 最大堆 */
typedef Heap MinHeap; /* 最小堆 */
#define MAXDATA 1000 /* 该值应根据具体情况定义为大于堆中所有可能元素的值 */
MaxHeap CreateHeap( int MaxSize )
{ /* 创建容量为MaxSize的空的最大堆 */
MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode));
H->Data = (ElementType *)malloc((MaxSize+1)*sizeof(ElementType));
H->Size = 0;
H->Capacity = MaxSize;
H->Data[0] = MAXDATA; /* 定义"哨兵"为大于堆中所有可能元素的值*/
return H;
}
bool IsFull( MaxHeap H )
{
return (H->Size == H->Capacity);
}
bool Insert( MaxHeap H, ElementType X )
{ /* 将元素X插入最大堆H,其中H->Data[0]已经定义为哨兵 */
int i;
if ( IsFull(H) ) {
printf("最大堆已满");
return false;
}
i = ++H->Size; /* i指向插入后堆中的最后一个元素的位置 */
for ( ; H->Data[i/2] < X; i/=2 )
H->Data[i] = H->Data[i/2]; /* 上滤X */
H->Data[i] = X; /* 将X插入 */
return true;
}
#define ERROR -1 /* 错误标识应根据具体情况定义为堆中不可能出现的元素值 */
bool IsEmpty( MaxHeap H )
{
return (H->Size == 0);
}
ElementType DeleteMax( MaxHeap H )
{ /* 从最大堆H中取出键值为最大的元素,并删除一个结点 */
int Parent, Child;
ElementType MaxItem, X;
if ( IsEmpty(H) ) {
printf("最大堆已为空");
return ERROR;
}
MaxItem = H->Data[1]; /* 取出根结点存放的最大值 */
/* 用最大堆中最后一个元素从根结点开始向上过滤下层结点 */
X = H->Data[H->Size--]; /* 注意当前堆的规模要减小 */
for( Parent=1; Parent*2<=H->Size; Parent=Child ) {
Child = Parent * 2;
if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
Child++; /* Child指向左右子结点的较大者 */
if( X >= H->Data[Child] ) break; /* 找到了合适位置 */
else /* 下滤X */
H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;
return MaxItem;
}
/*----------- 建造最大堆 -----------*/
void PercDown( MaxHeap H, int p )
{ /* 下滤:将H中以H->Data[p]为根的子堆调整为最大堆 */
int Parent, Child;
ElementType X;
X = H->Data[p]; /* 取出根结点存放的值 */
for( Parent=p; Parent*2<=H->Size; Parent=Child ) {
Child = Parent * 2;
if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
Child++; /* Child指向左右子结点的较大者 */
if( X >= H->Data[Child] ) break; /* 找到了合适位置 */
else /* 下滤X */
H->Data[Parent] = H->Data[Child];
}
H->Data[Parent] = X;
}
void BuildHeap( MaxHeap H )
{ /* 调整H->Data[]中的元素,使满足最大堆的有序性 */
/* 这里假设所有H->Size个元素已经存在H->Data[]中 */
int i;
/* 从最后一个结点的父节点开始,到根结点1 */
for( i = H->Size/2; i>0; i-- )
PercDown( H, i );
}
C语言描述:集合的定义和并集操作
#define MAXN 1000 /* 集合最大元素个数 */
typedef int ElementType; /* 默认元素可以用非负整数表示 */
typedef int SetName; /* 默认用根结点的下标作为集合名称 */
typedef ElementType SetType[MAXN]; /* 假设集合元素下标从0开始 */
void Union( SetType S, SetName Root1, SetName Root2 )
{ /* 这里默认Root1和Root2是不同集合的根结点 */
/* 保证小集合并入大集合 */
if ( S[Root2] < S[Root1] ) { /* 如果集合2比较大 */
S[Root2] += S[Root1]; /* 集合1并入集合2 */
S[Root1] = Root2;
}
else { /* 如果集合1比较大 */
S[Root1] += S[Root2]; /* 集合2并入集合1 */
S[Root2] = Root1;
}
}
SetName Find( SetType S, ElementType X )
{ /* 默认集合元素全部初始化为-1 */
if ( S[X] < 0 ) /* 找到集合的根 */
return X;
else
return S[X] = Find( S, S[X] ); /* 路径压缩 */
}
05-树7 堆中的路径 (25 分)
将一系列给定数字插入一个初始为空的小顶堆H[]。随后对任意给定的下标i,打印从H[i]到根结点的路径。
输入格式:
每组测试第1行包含2个正整数N和M(≤1000),分别是插入元素的个数、以及需要打印的路径条数。下一行给出区间[-10000, 10000]内的N个要被插入一个初始为空的小顶堆的整数。最后一行给出M个下标。
输出格式:
对输入中给出的每个下标i,在一行中输出从H[i]到根结点的路径上的数据。数字间以1个空格分隔,行末不得有多余空格。
#include<stdio.h>
#define MAXN 1001
#define MINH -10001
int H[MAXN],size;
void Insert(int x){
int i;
for(i=++size; H[i/2]> x; i/=2 )
H[i]=H[i/2];
H[i]=x;
}
void Creat(int n){
int i,x;
H[0]=MINH;
size=0;
for(i=0;i<n;i++){
scanf("%d",&x);
Insert(x);
}
}
void Print(int m){
int i,j;
for(i=0;i<m;i++){
scanf("%d",&j);
printf("%d",H[j]);
while(j>1){
j/=2;
printf(" %d",H[j]);
}
printf("\n");
}
}
int main(){
int n,m;
scanf("%d %d",&n,&m);
Creat(n);
Print(m);
return 0;
}
05-树8 File Transfer (25 分)
We have a network of computers and a list of bi-directional connections. Each of these connections allows a file transfer from one computer to another. Is it possible to send a file from any computer on the network to any other?
Input Specification:
Each input file contains one test case. For each test case, the first line contains N (2≤N≤10^4 ), the total number of computers in a network. Each computer in the network is then represented by a positive integer between 1 and N. Then in the following lines, the input is given in the format:
#include<stdio.h>
#define MAXN 10000
typedef int SetType[MAXN];
int Find(SetType S, int n){
if (S[n]<0)
return n;
else
return S[n]=Find(S, S[n]);
}
void Union(SetType S, int a, int b){
if (S[a]> S[b])
S[a]=b;
else{
if(S[a]==S[b])
S[a]--;
S[b]=a;
}
}
void Insert( SetType S){
int a, b;
int m, n;
scanf("%d %d",&a, &b);
m=Find(S, a-1);
n=Find(S, b-1);
if(m!=n)
Union(S, m, n);
}
void Initialization(SetType S, int n){
for(int i=0;i<n;i++)
S[i]=-1;
}
void Check( SetType S){
int a, b;
int m, n;
scanf("%d %d",&a, &b);
m=Find(S, a-1);
n=Find(S, b-1);
if(m!=n)
printf("no\n");
else
printf("yes\n");
}
void Finish( SetType S,int n){
int i,counter=0;
for(i=0;i<n ;i++){
if(S[i]<0)
counter++;
}
if(counter==1)
printf("The network is connected.\n");
else
printf("There are %d components.\n",counter);
}
int main(){
SetType S;
int n;
char c;
scanf("%d\n",&n);
Initialization(S,n);
do{
scanf("%c",&c);
switch(c){
case 'I': Insert(S);break;
case 'C': Check(S);break;
case 'S': Finish(S,n);break;
}
}while(c!='S');
return 0;
}
05-树9 Huffman Codes (30 分)
In 1953, David A. Huffman published his paper “A Method for the Construction of Minimum-Redundancy Codes”, and hence printed his name in the history of computer science. As a professor who gives the final exam problem on Huffman codes, I am encountering a big problem: the Huffman codes are NOT unique. For example, given a string “aaaxuaxz”, we can observe that the frequencies of the characters ‘a’, ‘x’, ‘u’ and ‘z’ are 4, 2, 1 and 1, respectively. We may either encode the symbols as {‘a’=0, ‘x’=10, ‘u’=110, ‘z’=111}, or in another way as {‘a’=1, ‘x’=01, ‘u’=001, ‘z’=000}, both compress the string into 14 bits. Another set of code can be given as {‘a’=0, ‘x’=11, ‘u’=100, ‘z’=101}, but {‘a’=0, ‘x’=01, ‘u’=011, ‘z’=001} is NOT correct since “aaaxuaxz” and “aazuaxax” can both be decoded from the code 00001011001001. The students are submitting all kinds of codes, and I need a computer program to help me determine which ones are correct and which ones are not.
Input Specification:
Each input file contains one test case. For each case, the first line gives an integer N (2≤N≤63), then followed by a line that contains all the N distinct characters and their frequencies in the following format:
c[1] f[1] c[2] f[2] … c[N] f[N]
where c[i] is a character chosen from {‘0’ - ‘9’, ‘a’ - ‘z’, ‘A’ - ‘Z’, ‘_’}, and f[i] is the frequency of c[i] and is an integer no more than 1000. The next line gives a positive integer M (≤1000), then followed by M student submissions. Each student submission consists of N lines, each in the format:
c[i] code[i]
where c[i] is the i-th character and code[i] is an non-empty string of no more than 63 '0’s and '1’s.
Output Specification:
For each test case, print in each line either “Yes” if the student’s submission is correct, or “No” if not.
Note: The optimal solution is not necessarily generated by Huffman algorithm. Any prefix code with code length being optimal is considered correct.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Maxn 64
int N, w[Maxn];
char ch[Maxn];
int codelen, cnt1, cnt2;
typedef struct TreeNode* Tree;
struct TreeNode {
int Weight;
Tree Left, Right;
};
typedef struct HeapNode* Heap;
struct HeapNode {
struct TreeNode Data[Maxn];
int Size;
};
Tree CreatTree() {
Tree T;
T = (Tree)malloc(sizeof(struct TreeNode));
T->Left = T->Right = NULL;
T->Weight = 0;
return T;
}
Heap CreatHeap() {
Heap H;
H = (Heap)malloc(sizeof(struct HeapNode));
H->Size = 0;
H->Data[0].Weight = -1;
return H;
}
void Insert(Heap H, struct TreeNode T) {
int i = ++H->Size;
for( ; T.Weight < H->Data[i/2].Weight; i /= 2)
H->Data[i] = H->Data[i/2];
H->Data[i] = T;
}
Tree Delete(Heap H) {
int parent, child;
struct TreeNode Temp = H->Data[H->Size--];
Tree T = CreatTree();
*T = H->Data[1];
for(parent = 1; 2*parent <= H->Size; parent = child) {
child = 2 * parent;
if(child != H->Size && H->Data[child].Weight > H->Data[child+1].Weight) child++;
if(Temp.Weight < H->Data[child].Weight) break;
H->Data[parent] = H->Data[child];
}
H->Data[parent] = Temp;
return T;
}
Tree Huffman(Heap H) {
Tree T = CreatTree(); //分配空间
while(H->Size != 1) {
T->Left = Delete(H);
T->Right = Delete(H);
T->Weight = T->Left->Weight + T->Right->Weight;
//printf("l = %d, r = %d, t = %d\n", T->Left->Weight, T->Right->Weight, T->Weight);
Insert(H, *T);
}
T = Delete(H);
return T;
}
void PreTravel(Tree T) {
if(T) {
printf("%d ", T->Weight);
PreTravel(T->Left);
PreTravel(T->Right);
}
}
int WPL(Tree T, int Depth) {
if(!T->Left && !T->Right)
return Depth*T->Weight;
else
return WPL(T->Left, Depth+1) + WPL(T->Right, Depth+1);
}
void JudgeTree(Tree T) {
if(T) {
if(T->Left && T->Right) cnt2++;
else if(!T->Left && !T->Right) cnt1++;
else cnt1 = 0;
JudgeTree(T->Left);
JudgeTree(T->Right);
}
}
int Judge() {
int i, j, wgh, flag = 1;
char s1[Maxn], s2[Maxn];
Tree T = CreatTree(), pt = NULL;
for(i = 0; i < N; i++) {
scanf("%s%s", s1, s2);
if(strlen(s2) > N) return 0;
for(j = 0; s1[0] != ch[j]; j++); wgh = w[j];
pt = T;//每次建树前先将指针移动到根节点上;
for(j = 0; s2[j]; j++) {
if(s2[j] == '0') {
if(!pt->Left) pt->Left = CreatTree();
pt = pt->Left;
}
if(s2[j] == '1') {
if(!pt->Right) pt->Right = CreatTree();
pt = pt->Right;
}
if(pt->Weight) flag = 0;
if(!s2[j+1]) {
if(pt->Left || pt->Right) flag = 0;//判断是否为前缀
pt->Weight = wgh;
}
//printf("w = %d\n", pt->Weight);
}
}
if(!flag) return 0;
cnt1 = cnt2 = 0;
JudgeTree(T);//判断是否不存在度数1的节点
if(cnt1 != cnt2 + 1) return 0;
//printf("wpl = %d\n", WPL(T, 0));
if(codelen == WPL(T, 0)) return 1;
else return 0;
}
int main() {
int i, n;
Heap H;
Tree T;
H = CreatHeap();
T = CreatTree();
scanf("%d", &N);
for(i = 0; i < N; i++) {
getchar();
scanf("%c %d", &ch[i], &w[i]);
H->Data[H->Size].Left = H->Data[H->Size].Right = NULL;
T->Weight = w[i];
Insert(H, *T);
}
//for(i = 1; i <= H->Size; i++) printf("%d ", H->Data[i].Weight);
T = Huffman(H); //PreTravel(T);
codelen = WPL(T, 0);
scanf("%d", &n);
while(n--) {
if(Judge()) printf("Yes\n");
else printf("No\n");
}
return 0;
}