【数据结构初学笔记15】第五章MOOC练习题

课程作业:

  1. 堆中的路径 将在“小白专场”中介绍C语言的实现方法,是建立最小堆的基本操作训练,一定要做;

  2. File Transfer 关于并查集,2005、2007年浙江大学计算机学院免试研究生上机考试题即由此题改编而来。“小白专场”中介绍了原始并查集算法的优化,听完课以后自己尝试一下;

  3. Huffman Codes 考察对Huffman编码的理解,程序可能略繁,量力而为。

1.堆中的路径

/*题意理解:将一系列数字插入一个初始为空的小顶堆H[]中,并打印从H[i]到根结点的路径*/
/*思路:1.创建最小空堆,最小堆的插入*/
/*2.打印路径时,注意父结点与子节点的序号关系*/
#include <stdio.h>
#include <stdlib.h>
#define ElementType int
#define MinData -10001

typedef struct HeapNode *HeapTree;
struct HeapNode
{
    ElementType *Elements; /*存储堆元素的数组指针*/
    int Size;              /*堆当前的元素个数*/
    int Capacity;          /*堆的最大容量*/
};
HeapTree CreateHeapMin(int Maxsize);          //创建最小堆
void InsertMin(HeapTree H, ElementType item); //最小堆的插入
int IsFull(HeapTree H);                       //判断堆是否满,满堆返回1
int IsEmpty(HeapTree H);                      //判断堆是否空,空堆返回1
int main(void)
{
    int N, M, item, i, j; /*N为插入堆中的元素个数,M为需要进行查找的元素个数*/
    HeapTree H;
    H = CreateHeapMin(1000); //创建一个空堆
    scanf("%d %d", &N, &M);
    // int R[M],Path[M];           /*存放被查找的元素,和查找路径上的元素*/
    for (i = 0; i < N; i++) /*输入N个元素,并插入到最小堆中*/
    {
        scanf("%d", &item);
        InsertMin(H, item);
    }
    for (i = 0; i < M; i++)
    {
        scanf("%d", &j);
        printf("%d", H->Elements[j]);
        while (j > 1)
        {
            j /= 2;
            printf(" %d", H->Elements[j]);
        }
        printf("\n");
    }
    return 0;
}
// 创建最小堆
HeapTree CreateHeapMin(int Maxsize) //创建容量为Maxsize的空堆
{
    HeapTree H = (HeapTree)malloc(sizeof(struct HeapNode));
    H->Elements = (ElementType *)malloc(sizeof(ElementType) * (Maxsize + 1));
    H->Size = 0;
    H->Capacity = Maxsize;
    H->Elements[0] = MinData; //定义哨兵
    return H;
}
void InsertMin(HeapTree H, ElementType item) //将元素item插入到最大堆H中,其中哨兵为H->ElementType[0]
{
    int i;
    if (IsFull(H))
    {
        printf("堆已满\n");
        return;
    }
    i = ++H->Size;
    for (; H->Elements[i / 2] > item; i = i / 2)
    {
        H->Elements[i] = H->Elements[i / 2]; //向下过滤比插入值小的结点
    }
    H->Elements[i] = item; // item的插入位置
}
int IsFull(HeapTree H) //判断堆是否满,满堆返回1
{
    return (H->Size == H->Capacity);
}
int IsEmpty(HeapTree H) //判断堆是否空,空堆返回1
{
    return (H->Size == 0);
}
/*期待输入*/
// 5 3
// 46 23 26 24 10
// 5 4 3
/*期待输出*/
// 24 23 10
// 46 23 10
// 26 10

2.File Transfer

/*题目介绍:输入计算机数目N,C i j表示查询第i台和第j台计算机是否连接;I i j表示连接第i台和第j台计算机;
S表示输入结束,若计算机以全部连接,打印“The network is connected.”,否则打印“There are m components.”,其中m表示计算机集合个数*/
/*思路:1.使用集合的简化表示(使用数组来存储集合,数组下标对应元素值,数组值对应根结点元素下标)
2.集合查找时选用路径压缩的方法(将每一个元素都调整为指向根结点)注意:将N台计算机映射到集合0-(N-1)范围
3.集合并操作选用按秩归并的方法(层数,节点个数)*/
/*具体实现见下文代码*/

#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10001
/*集合的简化表示:将有限集合的N个元素映射到整数0-(N-1),集合元素用下标来表示,其存储的内容为对应的父结点下标*/
typedef int ElementType; /*默认元素可以用非负整数表示*/
typedef int SetName;     /*默认用根结点的下标作为集合名称*/
typedef ElementType SetType[MaxSize];

void Input_connection(SetType S);     /*连接两台计算机*/
void Check_connection(SetType S);     /*检查两台计算机是否连接*/
void Check_network(SetType S, int N); /*检查整个计算机网络*/
SetName Find(SetType S, ElementType X);
void Union(SetType S, SetName Root1, SetName Root2);
// Initialization(SetType S, int N);
int main(void)
{
    SetType S;
    int N, i;
    char Comd;
    /*初始化集合*/
    scanf("%d", &N);
    getchar();
    for (i = 0; i < N; i++)
        S[i] = -1;
    do
    {
        Comd = getchar();
        switch (Comd)
        {
        case 'I': /*连接两台计算机*/
            Input_connection(S);
            break;
        case 'C': /*检查两台计算机是否连接*/
            Check_connection(S);
            break;
        case 'S': /*检查整个计算机网络*/
            Check_network(S, N);
            break;
        }
    } while (Comd != 'S');
    return 0;
}
void Input_connection(SetType S)
{ /*连接两台计算机*/
    ElementType m1, m2;
    SetName Root1, Root2;
    scanf("%d%d", &m1, &m2);
    getchar();
    Root1 = Find(S, m1 - 1);
    Root2 = Find(S, m2 - 1);
    if (Root1 != Root2) /*将两台计算机的根结点连接起来*/
        Union(S, Root1, Root2);
}
void Check_connection(SetType S)
{ /*检查两台计算机是否连接*/
    ElementType m1, m2;
    SetName Root1, Root2;
    scanf("%d%d", &m1, &m2);
    getchar();
    Root1 = Find(S, m1 - 1);
    Root2 = Find(S, m2 - 1);
    if (Root1 == Root2)
        printf("yes\n");
    else
        printf("no\n");
}
void Check_network(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.", counter);
}
SetName Find(SetType S, ElementType X)
{ /*默认集合元素全部初始化为-1*/
    /*路径压缩*/
    if (S[X] < 0)
        return X;
    else
        return S[X] = Find(S, S[X]); /*递归:遇到根结点时,返回根结点下标X2,将X2赋值给上一个结点S[X1]=X2,并继续返回X1*/
}
void Union(SetType S, SetName Root1, SetName Root2)
{ /* 这里默认Root1和Root2是不同集合的根结点 */
    /*按秩归并:元素个数*/
    if (S[Root1] < S[Root2])
    { /*树1元素更多一些,将集合2指向集合1*/
        S[Root1] += S[Root2];
        S[Root2] = Root1;
    }
    else
    { /*树2元素更多一些,将集合1指向集合2*/
        S[Root2] += S[Root1];
        S[Root1] = Root2;
    }
    // /*按秩归并:树高*/
    // if (S[Root1] < S[Root2])
    //     S[Root2] = Root1;
    // else
    // {
    //     if (S[Root1 == Root2])
    //         S[Root2]--; /*树高相同时,将集合1指向集合2*/
    //     S[Root1] = Root2;
    // }
}

3.Huffman Codes

没做出来,暂时没思路,后面有时间继续看一下

结束

课程来源:浙江大学数据结构慕课MOOC

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值