【2020-MOOC-浙江大學-陳越、何欽銘-數據結構】樹和堆(第五週的筆記和編程作業)

〇、前言

這兩週開始跟着【MOOC-浙江大學-陳越、何欽銘-數據結構】進行數據結構與算法的學習,特此記錄複習一下,雖然記不住,但是一直記一直記一直記,成爲復讀機就好了。
在這裏插入圖片描述

一、堆

優先隊列(Priority Queue):特殊的“隊列”,取出元素的順序是依照元素的優先權(關鍵字)大小,而不是元素進入隊列的先後順序。
在這裏插入圖片描述

二、堆的基本操作

在這裏插入圖片描述

  • MaxHeap Create( int MaxSize ):創建一個空的最大堆。
  • Boolean IsFull( MaxHeap H ):判斷最大堆H是否已滿。
  • Insert( MaxHeap H, ElementType item ):將元素item插入最大堆H。
  • Boolean IsEmpty( MaxHeap H ):判斷最大堆H是否爲空。
  • ElementType DeleteMax( MaxHeap H ):返回H中最大元素(高優先級)。

三、哈夫曼樹

在這裏插入圖片描述

四、集合及運算

  • 集合運算:交、並、補、差,判定一個元素是否屬於某一集合
  • 並查集:集合並、查某元素屬於什麼集合
  • 並查集問題中集合存儲如何實現?
    • 可以用樹結構表示集合,樹的每個結點代表一個集合元素

五、堆中的路徑

在這裏插入圖片描述

六、課後題

在這裏插入圖片描述

1、05-樹7 堆中的路徑 (25分)

在這裏插入圖片描述
輸入樣例:

5 3
46 23 26 24 10
5 4 3

輸出樣例:

24 23 10
46 23 10
26 10


#include <stdio.h> 

#define MAXN 1001
#define MINH -10001

int H[MAXN], size;
void Create ()
{
	size = 0;
	H[0] = MINH;
	/*設置“崗哨”*/
}

void Insert ( int X )
{
	/* 將X插入H。這裏省略檢查堆是否已滿的代碼 */
	int i;
	for (i=++size; H[i/2] > X; i/=2)
		H[i] = H[i/2];
	H[i] = X;
}

int main()
{ 
	int n, m, x, i, j;
	scanf("%d %d", &n, &m);
	Create(); /* 堆初始化 */
	for (i=0; i<n; i++) { /*以逐個插入方式建堆 */
		scanf("%d", &x);
		Insert(x);
	}
	for (i=0; i<m; i++) {
		scanf("%d", &j);
		printf("%d", H[j]);
		while (j>1) { /*沿根方向輸出各結點*/
			j /= 2;
			printf(" %d", H[j]);
		}
		printf("\n");
	}
	return 0;
}

在這裏插入圖片描述


2、05-樹8 File Transfer (25分)

在這裏插入圖片描述
在這裏插入圖片描述
Sample Input 1:

5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S

Sample Output 1:

no
no
yes
There are 2 components.

Sample Input 2:

5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
I 1 3
C 1 5
S

Sample Output 2:

no
no
yes
yes
The network is connected.


#include <stdio.h> 

#define MaxSize 10001

typedef int ElementType; /*默認元素可以用非負整數表示*/
typedef int SetName; /*默認用根結點的下標作爲集合名稱*/
typedef ElementType SetType[MaxSize];

SetName Find( SetType S, ElementType X )
{ 
	/* 默認集合元素全部初始化爲-1 */
	for ( ; S[X]>=0; X=S[X] ) ;
	return X;
}

void Union( SetType S, SetName Root1, SetName Root2 )
{ 
	if ( S[Root2]<S[Root1] ){
		S[Root2] += S[Root1];
		S[Root1] = Root2;
	}
	else {
		S[Root1] += S[Root2];
		S[Root2] = Root1;
	}
}

void Input_connection( SetType S )
{ 
	ElementType u, v;
	SetName Root1, Root2;
	scanf("%d %d\n", &u, &v);
	Root1 = Find(S, u-1);
	Root2 = Find(S, v-1);
	if ( Root1 != Root2 )
		Union( S, Root1, Root2 );
}

void Check_connection( SetType S )
{ 
	ElementType u, v;
	SetName Root1, Root2;
	scanf("%d %d\n", &u, &v);
	Root1 = Find(S, u-1);
	Root2 = Find(S, v-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.\n", counter);
}
Initialization( SetType S, int n ){
	int i;
	for(i = 0; i < n; i++) S[i] = -1;
}

int main()
{ 
	SetType S;
	int n;
	char in;
	scanf("%d\n", &n);
	Initialization( S, n );
	do {
		scanf("%c", &in);
		switch (in) {
		case 'I': Input_connection( S ); break;
		case 'C': Check_connection( S ); break;
		case 'S': Check_network( S, n ); break;
		}
	} while ( in != 'S');
	return 0;
}

在這裏插入圖片描述


3、05-樹9 Huffman Codes (30分)

在這裏插入圖片描述
在這裏插入圖片描述
Sample Input:

7
A 1 B 1 C 1 D 3 E 3 F 6 G 6
4
A 00000
B 00001
C 0001
D 001
E 01
F 10
G 11
A 01010
B 01011
C 0100
D 011
E 10
F 11
G 00
A 000
B 001
C 010
D 011
E 100
F 101
G 110
A 00000
B 00001
C 0001
D 001
E 00
F 10
G 11

Sample Output:

Yes
Yes
No
No


#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;
        Insert(H, *T);
    }
    T = Delete(H);
    return T;
}
 
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;
            }
        }
    }
    if(!flag) return 0;
    cnt1 = cnt2 = 0;
    JudgeTree(T);//判斷是否不存在度數1的節點
    if(cnt1 != cnt2 + 1) return 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);
    }
    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;
}

在這裏插入圖片描述

總結

簡單總結下這周的學習內容,我哭了,筆斷了,電腦死機了,

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章