PTA(浙大數據結構,c語言)

01-複雜度1 最大子列和問題node

給定K個整數組成的序列{ N​1​​, N​2​​, ..., N​K​​ },「連續子列」被定義爲{ N​i​​, N​i+1​​, ..., N​j​​ },其中 1。「最大子列和」則被定義爲全部連續子列元素的和中最大者。例如給定序列{ -2, 11, -4, 13, -5, -2 },其連續子列{ 11, -4, 13 }有最大的和20。現要求你編寫程序,計算給定整數序列的最大子列和。git

本題旨在測試各類不一樣的算法在各類數據狀況下的表現。各組測試數據特色以下:算法

數據1:與樣例等價,測試基本正確性;數組

數據2:102個隨機整數;微信

數據3:103個隨機整數;網絡

數據4:104個隨機整數;app

數據5:105個隨機整數;less

輸入格式:dom

輸入第1行給出正整數K (≤);第2行給出K個整數,其間以空格分隔。ide

輸出格式:

在一行中輸出最大子列和。若是序列中全部整數皆爲負數,則輸出0。

輸入樣例:

6

-2 11 -4 13 -5 -2

輸出樣例:

20

 1 #include <stdio.h>
 2 
 3 //分而治之
 4 int Max3( int A, int B, int C );  5 int DivideAndConquer( int List[], int left, int right );  6 int MaxSubseqSum3( int List[], int N );  7 
 8 int main()  9 { 10     int arr[100000]; 11     int n; 12     scanf("%d",&n); 13     for (int i = 0; i < n; ++i) 14  { 15         scanf("%d",&arr[i]); 16  } 17     printf("%d",MaxSubseqSum3(arr, n)); 18     return 0; 19 } 20 
21 int Max3( int A, int B, int C ) 22 { /* 返回3個整數中的最大值 */
23     return A > B ? A > C ? A : C : B > C ? B : C; 24 } 25  
26 int DivideAndConquer( int List[], int left, int right ) 27 { /* 分治法求List[left]到List[right]的最大子列和 */
28     int MaxLeftSum, MaxRightSum; /* 存放左右子問題的解 */
29     int MaxLeftBorderSum, MaxRightBorderSum; /*存放跨分界線的結果*/
30  
31     int LeftBorderSum, RightBorderSum; 32     int center, i; 33  
34     if( left == right )  { /* 遞歸的終止條件,子列只有1個數字 */
35         if( List[left] > 0 )  return List[left]; 36         else return 0; 37  } 38  
39     /* 下面是"分"的過程 */
40     center = ( left + right ) / 2; /* 找到中分點 */
41     /* 遞歸求得兩邊子列的最大和 */
42     MaxLeftSum = DivideAndConquer( List, left, center ); 43     MaxRightSum = DivideAndConquer( List, center+1, right ); 44  
45     /* 下面求跨分界線的最大子列和 */
46     MaxLeftBorderSum = 0; LeftBorderSum = 0; 47     for( i=center; i>=left; i-- ) { /* 從中線向左掃描 */
48         LeftBorderSum += List[i]; 49         if( LeftBorderSum > MaxLeftBorderSum ) 50             MaxLeftBorderSum = LeftBorderSum; 51     } /* 左邊掃描結束 */
52  
53     MaxRightBorderSum = 0; RightBorderSum = 0; 54     for( i=center+1; i<=right; i++ ) { /* 從中線向右掃描 */
55         RightBorderSum += List[i]; 56         if( RightBorderSum > MaxRightBorderSum ) 57             MaxRightBorderSum = RightBorderSum; 58     } /* 右邊掃描結束 */
59  
60     /* 下面返回"治"的結果 */
61     return Max3( MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum ); 62 } 63  
64 int MaxSubseqSum3( int List[], int N ) 65 { /* 保持與前2種算法相同的函數接口 */
66     return DivideAndConquer( List, 0, N-1 ); 67 }

 

 
 1 #include <stdio.h>
 2 
 3 //在線處理
 4 int MaxSubSeqSum(int a[], int k)  5 {  6     int ThisSum, MaxSum;  7     ThisSum = MaxSum = 0;  8     for(int i=0; i<k; ++i){  9         ThisSum += a[i]; 10         if(ThisSum > MaxSum) 11             MaxSum = ThisSum; 12         else if(ThisSum < 0) 13             ThisSum = 0; 14  } 15     return MaxSum; 16 } 17 int main( ) { 18     
19     const int N = 100001; 20     int a[N]; 21     int k = 0; 22     scanf("%d",&k); 23     for(int i=0; i<k; ++i) 24         scanf("%d",&a[i]); 25     printf("%d\n",MaxSubSeqSum(a,k)); 26     
27     return 0; 28 }

01-複雜度2 Maximum Subsequence Sum

Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A continuous subsequence is defined to be { N​i​​, N​i+1​​, ..., N​j​​ } where 1. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (≤). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:

10

-10 1 2 3 4 -5 -23 3 7 -21

Sample Output:

10 1 4

 
 1 #include <stdio.h>
 2 #define N 100000
 3 void max_sub_sum(int arr[], int n)  4 {  5     int this_sum = 0, max_sum = -1;  6     int first_num, last_num;  7     int index_first = 0; //第一個元素下標
 8     for (int i = 0; i < n; ++i)  9  { 10         this_sum += arr[i]; 11         if (this_sum > max_sum)//元素所有爲負數進不來
12         {    //產生最大值,第一個元素,最後一個元素是肯定的
13             max_sum = this_sum; //最大值
14             first_num = arr[index_first];//第一個元素 
15             last_num = arr[i];//最後一個元素 
16  } 17         else if (this_sum < 0) 18  { 19             this_sum = 0; 20             index_first = i+1; //更新第一個元素的下標
21  } 22  } 23     if(max_sum == -1) printf("0 %d %d\n", arr[0], arr[n-1]); 24     else printf("%d %d %d\n", max_sum, first_num, last_num); 25 } 26 
27 int main() 28 { 29     int arr[N] = {0}; 30     int n; 31     scanf("%d", &n); 32     for (int i = 0; i < n; ++i) 33  { 34         scanf("%d", &arr[i]); 35  } 36  max_sub_sum(arr, n); 37     return 0; 38 }

01-複雜度3 二分查找

本題要求實現二分查找算法。

函數接口定義:

Position BinarySearch( List L, ElementType X );

其中List結構定義以下:

typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Position Last; /* 保存線性表中最後一個元素的位置 */ };

L是用戶傳入的一個線性表,其中ElementType元素能夠經過>、=、<進行比較,而且題目保證傳入的數據是遞增有序的。函數BinarySearch要查找X在Data中的位置,即數組下標(注意:元素從下標1開始存儲)。找到則返回下標,不然返回一個特殊的失敗標記NotFound。

裁判測試程序樣例:

#include <stdio.h> #include <stdlib.h>
#define MAXSIZE 10
#define NotFound 0 typedef int ElementType; typedef int Position; typedef struct LNode *List; struct LNode { ElementType Data[MAXSIZE]; Position Last; /* 保存線性表中最後一個元素的位置 */ }; List ReadInput(); /* 裁判實現,細節不表。元素從下標1開始存儲 */ Position BinarySearch( List L, ElementType X ); int main() { List L; ElementType X; Position P; L = ReadInput(); scanf("%d", &X); P = BinarySearch( L, X ); printf("%d\n", P); return 0; } /* 你的代碼將被嵌在這裏 */

輸入樣例1:

5

12 31 55 89 101

31

輸出樣例1:

2

輸入樣例2:

3

26 78 233

31

輸出樣例2:

0

 1 Position BinarySearch( List L, ElementType X )  2 {  3     Position position = NotFound;  4     Position left = 1;  5     Position right = L->Last;  6 
 7     while(left <= right){  8         Position mid = (left+right)/2;  9         if(L->Data[mid] > X){ 10             right = mid - 1; 11  } 12         else if(L->Data[mid]<X){ 13             left = mid + 1; 14  } 15         else{ 16             position = mid; 17             break; 18  } 19  } 20     return position; 21 }

02-線性結構1 兩個有序鏈表序列的合併

本題要求實現一個函數,將兩個鏈表表示的遞增整數序列合併爲一個非遞減的整數序列。

函數接口定義:

List Merge( List L1, List L2 );

其中List結構定義以下:

typedef struct Node *PtrToNode; struct Node { ElementType Data; /* 存儲結點數據 */ PtrToNode Next; /* 指向下一個結點的指針 */ }; typedef PtrToNode List; /* 定義單鏈表類型 */

L1和L2是給定的帶頭結點的單鏈表,其結點存儲的數據是遞增有序的;函數Merge要將L1和L2合併爲一個非遞減的整數序列。應直接使用原序列中的結點,返回歸併後的帶頭結點的鏈表頭指針。

裁判測試程序樣例:

#include <stdio.h> #include <stdlib.h> typedef int ElementType; typedef struct Node *PtrToNode; struct Node { ElementType Data; PtrToNode Next; }; typedef PtrToNode List; List Read(); /* 細節在此不表 */
void Print( List L ); /* 細節在此不表;空鏈表將輸出NULL */ List Merge( List L1, List L2 ); int main() { List L1, L2, L; L1 = Read(); L2 = Read(); L = Merge(L1, L2); Print(L); Print(L1); Print(L2); return 0; } /* 你的代碼將被嵌在這裏 */

輸入樣例:

3

1 3 5

5

2 4 6 8 10

輸出樣例:

1 2 3 4 5 6 8 10

NULL

NULL

 1 List Merge( List L1, List L2 )  2 {  3     List pa,pb,pc,L;  //返回L
 4     L = (List)malloc(sizeof(struct Node));  5     pa=L1->Next;  //傳進來的2個帶頭結點的鏈表L1,L2
 6     pb=L2->Next;  7     pc = L;  //新鏈表頭指針賦值
 8     while(pa && pb)  9  { 10         if(pa->Data <= pb->Data) 11  { 12             pc->Next = pa; //a前插 
13             pc = pa;       //更新c指針
14             pa = pa->Next; //更新a指針
15  } 16         else  
17  { 18             pc->Next = pb; //b前插 
19             pc = pb;       //更新c指針
20             pb = pb->Next; //更新b指針 
21  } 22  } 23     pc->Next = pa ? pa : pb;//連接剩餘結點 
24     L1->Next = NULL;   //按題目要求鏈表L1,L2置空
25     L2->Next = NULL; 26     return L; 27 }

02-線性結構2 一元多項式的乘法與加法運算

設計函數分別求兩個一元多項式的乘積與和。

輸入格式:

輸入分2行,每行分別先給出多項式非零項的個數,再以指數遞降方式輸入一個多項式非零項係數和指數(絕對值均爲不超過1000的整數)。數字間以空格分隔。

輸出格式:

輸出分2行,分別以指數遞降方式輸出乘積多項式以及和多項式非零項的係數和指數。數字間以空格分隔,但結尾不能有多餘空格。零多項式應輸出0 0。

輸入樣例:

4 3 4 -5 2  6 1  -2 0

3 5 20  -7 4  3 1

輸出樣例:

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1

5 20 -4 4 -5 2 9 1 -2 0

 1 #include <stdio.h>
 2 #include <malloc.h>
 3 
 4 //結點
 5 typedef struct Node *List;  6 struct Node{  7     int coe;  //係數 
 8     int exp;   //指數 
 9  List Next;  10 };  11 
 12 //讀入鏈表 
 13 List Read()  14 {  15     List head = NULL, L = NULL;  16     int n;  17     scanf("%d", &n);//n個結點
 18     
 19     for(int i=0; i<n; i++)  20  {  21         List p = (List)malloc(sizeof(struct Node));  22         scanf("%d %d", &p->coe, &p->exp);  23         p->Next = NULL;  //新結點
 24         
 25         if(i == 0) head = L = p; //鏈表第一個結點
 26         else{  27             L->Next = p; //鏈入鏈表
 28             L = L->Next; //鏈表指針更新
 29  }  30  }  31     return head;  32 }  33 
 34 //加法運算 
 35 List addition(List L1,List L2)  36 {  37  List head, add;  38     head = add = (List)malloc(sizeof(struct Node));  39     head->Next = NULL; //頭結點(爲了排序調用)
 40     
 41     while(L1 && L2)  42  {  43         List p = (List)malloc(sizeof(struct Node));  44         p->Next = NULL;  45         
 46         if(L1->exp == L2->exp){ //指數相等 
 47             p->coe = L1->coe + L2->coe; //係數相加
 48             p->exp = L1->exp; //指數賦值
 49             L1 = L1->Next; //更新L1
 50             L2 = L2->Next; //更新L2
 51         }else if(L1->exp < L2->exp){//L2結點指數大
 52             p->coe = L2->coe; //L2結點係數賦值
 53             p->exp = L2->exp; //指數賦值
 54             L2 = L2->Next;    //更新L2
 55         }else {             // L1結點指數大
 56             p->coe = L1->coe; //L1 結點係數賦值
 57             p->exp = L1->exp; //指數賦值
 58             L1 = L1->Next;  //更新L1
 59  }  60         
 61         add->Next = p;  62         add = add->Next;  63  }  64     if(L1)  // 若L1不等於NULL, 將剩下結點加入其後, 不影響原鏈表 
 65         add->Next = L1;  66     else if(L2)  // 同理
 67         add->Next = L2;  68     List ret = head->Next;  69     free(head);  70     return ret;  71 }  72 
 73 //乘法運算 
 74 List multiplication(List L1,List L2){  75     
 76     List mul = NULL, head = NULL, tL2 = L2;  77     
 78     for(; L1; L1 = L1->Next)  79  {  80         for(L2 = tL2; L2; L2 = L2->Next)  81  {  82             List p = (List)malloc(sizeof(struct Node));  83             p->Next = NULL;  84             p->coe = L1->coe * L2->coe;  // 係數相乘
 85             p->exp = L1->exp + L2->exp;  // 指數相加
 86             if(mul == NULL) head = mul = p;  87             else{  88                 head = addition(p, mul); //結點排序 
 89                 mul = head; // 從新肯定開頭 
 90  }  91  }  92  }  93     
 94     return head;  95 }  96 
 97 //打印
 98 void Print(List L)  99 { 100     int flag = 1; 101     while(L) 102  { 103         if(!flag && L->coe)//係數不爲0
104             printf(" "); 105         if(L->coe){ //係數爲0不輸出 
106             printf("%d %d",L->coe,L->exp); 107             flag =0; 108  } 109         L = L->Next; 110  } 111     if(flag) //空鏈表
112         printf("0 0"); 113     printf("\n"); 114 } 115 
116 int main() 117 { 118  List L1,L2,add,mul; 119     L1 = Read(); //鏈表L1
120     L2 = Read(); //鏈表L2
121     add = addition(L1,L2); 122     mul = multiplication(L1,L2); 123     Print(mul); //打印乘法結果
124     Print(add); //打印加法結果
125     return 0; 126 }
 1 #include <stdio.h>
 2 #include <malloc.h>
 3 // 結點
 4 typedef struct PolyNode *Polynomial;  5 struct PolyNode {  6     int coef;  7     int expon;  8  Polynomial link;  9 };  10 // 0.0
 11 void DestroyPoly(Polynomial* p){  12     while(*p)  13  {  14         Polynomial t = *p;  15         *p = (*p)->link;  16         free(t);  17  }  18 }  19 // 0.1
 20 void Attach( int c, int e, Polynomial *pRear )  21 {  22  Polynomial P;  23     P = (Polynomial)malloc(sizeof(struct PolyNode));  24     P->coef = c;    /* 對新結點賦值 */  
 25     P->expon = e;  26     P->link = NULL;  27     
 28     (*pRear)->link = P;  /* 新結點插到pRear後面 */  
 29     *pRear = P; /* 修改pRear值 */ 
 30 }  31 // 1.
 32 Polynomial ReadPoly()  33 {  34  Polynomial P, Rear, t;  35     int c, e, N;  36     scanf("%d", &N);  37     /* 頭結點 */ 
 38     P = Rear = (Polynomial)malloc(sizeof(struct PolyNode));  39     Rear->link = NULL;  40     while ( N-- )  41  {  42         scanf("%d %d", &c, &e);  43         Attach(c, e, &Rear);  44  }  45     t = P;  46     P = P->link;  47     free(t);  /* 刪除臨時生成的頭結點 */ 
 48     return P;  49 }  50 //2.
 51 Polynomial Add( Polynomial P1, Polynomial P2 )  52 {  53  Polynomial P, t1, t2, Rear, t;  54     int c, e;  55     t1 = P1;  56     t2 = P2;  57     P = Rear = (Polynomial)malloc(sizeof(struct PolyNode));  58     Rear->link = NULL;  59     
 60     while (t1 && t2)  61  {  62         if (t1->expon == t2->expon) {  63             e = t1->expon;  64             c = t1->coef + t2->coef;  65             if(c) Attach(c, e, &Rear);  66             t1 = t1->link;  67             t2 = t2->link;  68  }  69         else if (t1->expon > t2->expon) {  70             e = t1->expon;  71             c = t1->coef;  72             if(c) Attach(c, e, &Rear);  73             t1 = t1->link;  74  }  75         else {  76             e = t2->expon;  77             c = t2->coef;  78             if(c) Attach(c, e, &Rear);  79             t2 = t2->link;  80  }  81  }  82     
 83     while (t1) {  84         e = t1->expon;  85         c = t1->coef;  86         if(c) Attach(c, e, &Rear);  87         t1 = t1->link;  88  }  89     while (t2) {  90         e = t2->expon;  91         c = t2->coef;  92         if(c) Attach(c, e, &Rear);  93         t2 = t2->link;  94  }  95     
 96     t = P;  97     P = P->link;  98     free(t);  /* 刪除臨時生成的頭結點 */ 
 99     return P; 100 } 101 //3.0
102 Polynomial Mult( Polynomial P1, Polynomial P2 ) 103 { 104  Polynomial P, Mul, t1, t2, t; 105     int c, e; 106 
107     if (!P1 || !P2) return NULL; 108  
109     t1 = P1; 110     t2 = P2; 111     P = Mul = NULL; 112     
113     for(; t1; t1 = t1->link) 114  { 115         for (t2 = P2; t2;  t2 = t2->link) 116  { 117             e = t1->expon + t2->expon; 118             c = t1->coef * t2->coef; 119             if(c) 120  { 121                 t = (Polynomial)malloc(sizeof(struct PolyNode)); 122                 t->coef = c; 123                 t->expon = e; 124                 t->link = NULL; 125                 
126                 if(Mul == NULL) P = Mul = t; 127                 else{ 128                     P = Add(t, Mul); 129                     free(t); 130                     DestroyPoly(&Mul); 131                     Mul = P; 132  } 133  } 134  } 135  } 136 
137     return P; 138 } 139 
140 #ifdef N 141 //3.1
142 Polynomial Mult( Polynomial P1, Polynomial P2 ) 143 { 144  Polynomial P, Rear, t1, t2, t; 145     int c, e; 146 
147     if (!P1 || !P2) return NULL; 148  
149     t1 = P1; 150     t2 = P2; 151     P = Rear = (Polynomial)malloc(sizeof(struct PolyNode)); 152     Rear->link = NULL; // P->link = NULL;
153     
154     while (t2) /* 先用P1的第1項乘以P2,獲得P */ 
155  { 156         Attach(t1->coef*t2->coef, t1->expon+t2->expon, &Rear); 157         t2 = t2->link; 158  } 159     
160     t1 = t1->link;/* 從第2項開始逐項相乘 */ 
161     for(; t1; t1 = t1->link) 162  { 163         Rear = P; 164         for (t2 = P2; t2;  t2 = t2->link) 165  { 166             e = t1->expon + t2->expon; 167             c = t1->coef * t2->coef; 168             while (Rear->link && Rear->link->expon > e)//指數大 
169                 Rear = Rear->link; 170             if (Rear->link && Rear->link->expon == e)//指數相等 
171  { 172                 if (Rear->link->coef + c) /* 係數和大於0 */  
173                     Rear->link->coef += c; 174                 else {              /* 和等於0 */    
175                     t = Rear->link; 176                     Rear->link = t->link; 177                     free(t); 178  } 179  } 180             else {                                 //指數小
181                 t = (Polynomial)malloc(sizeof(struct PolyNode)); 182                 t->coef = c; 183                 t->expon = e; 184                 t->link = Rear->link; 185                 Rear->link = t; 186                 Rear = Rear->link; 187  } 188  } 189  } 190     t = P; 191     P = P->link; 192     free(t);  /* 刪除臨時生成的頭結點 */ 
193     return P; 194 } 195 #endif
196 //4.
197 void PrintPoly( Polynomial P ) 198 {   /* 輸出多項式 */  
199     int flag = 0;  /* 輔助調整輸出格式用 */ 
200 
201     if (!P) {printf("0 0\n"); return;} 202 
203     while ( P ) 204  { 205         if (!flag) flag = 1; 206         else    printf(" "); 207         printf("%d %d", P->coef, P->expon); 208         P = P->link; 209  } 210     printf("\n"); 211 } 212  
213 int main() 214 { 215  Polynomial P1, P2, PP, PS; 216     
217     P1 = ReadPoly(); 218     P2 = ReadPoly(); 219     PP = Mult( P1, P2 ); 220  PrintPoly( PP ); 221     PS = Add( P1, P2 ); 222  PrintPoly( PS ); 223     
224     return 0; 225 }

02-線性結構3 Reversing Linked List

Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.

Input Specification:

Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤) which is the total number of nodes, and a positive K (≤) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Data Next

where Address is the position of the node, Data is an integer, and Next is the position of the next node.

Output Specification:

For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:

00100 6 4

00000 4 99999

00100 1 12309

68237 6 -1

33218 3 00000

99999 5 68237

12309 2 33218

Sample Output:

00000 4 33218

33218 3 12309

12309 2 00100

00100 1 99999

99999 5 68237

68237 6 -1

 1 /* 
 2 1.結點的地址用數組的下標表示,經過數組下標能夠索引到結點的Data值,結點的Next值;  3 2.從首結點的地址FirstAdd開始,經過索引Next把結點的地址串起來;  4 3.用一個順序表List連續存儲結點的地址,結點的關係是連續的下標表示,由於表元素值就是結點地址;  5 4.List逆序就是地址逆序,經過逆序後的地址(結點下標)能夠索引到結點,List的下一個元素值,  6 就是結點的下一個結點地址;  7  */
 8 #include<stdio.h>
 9 #define MaxSize 100005
10 int main() 11 { 12     int Data[MaxSize]; 13     int Next[MaxSize]; 14     int list[MaxSize]; 15     int FirstAdd,N,K; 16     scanf("%d %d %d",&FirstAdd,&N,&K); 17     for(int i=0;i<N;i++){ 18         int tmpAdd,tmpData,tmpNext; 19         scanf("%d %d %d",&tmpAdd,&tmpData,&tmpNext); 20         Data[tmpAdd] = tmpData; 21         Next[tmpAdd] = tmpNext; 22  } 23     int sum=0;   // 累計有效結點數 
24     while(FirstAdd!=-1){   // 當尾結點爲 -1 時結束 
25         list[sum++] = FirstAdd;   // 記錄全部Address
26         FirstAdd = Next[FirstAdd];  // 找下一個結點 
27  } 28     for(int i=0;i<sum-sum%K;i+=K){  // 每 K 個結點一個區間 
29         for(int j=0;j<K/2;j++){  // 反轉鏈表
30             int t = list[i+j]; 31             list[i+j] = list[i+K-j-1]; 32             list[i+K-j-1] = t; 33  } 34  } 35     for(int i=0;i<sum-1;i++) 36         printf("%05d %d %05d\n",list[i],Data[list[i]],list[i+1]); 37     printf("%05d %d -1\n",list[sum-1],Data[list[sum-1]]); 38     return 0; 39 }

02-線性結構4 Pop Sequence

Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, ..., N and pop randomly. You are supposed to tell if a given sequence of numbers is a possible pop sequence of the stack. For example, if M is 5 and N is 7, we can obtain 1, 2, 3, 4, 5, 6, 7 from the stack, but not 3, 2, 1, 7, 5, 6, 4.

Input Specification:

Each input file contains one test case. For each case, the first line contains 3 numbers (all no more than 1000): M (the maximum capacity of the stack), N (the length of push sequence), and K (the number of pop sequences to be checked). Then K lines follow, each contains a pop sequence of N numbers. All the numbers in a line are separated by a space.

Output Specification:

For each pop sequence, print in one line "YES" if it is indeed a possible pop sequence of the stack, or "NO" if not.

Sample Input:

5 7 5

1 2 3 4 5 6 7

3 2 1 7 5 6 4

7 6 5 4 3 2 1

5 6 4 3 7 2 1

1 7 6 5 4 3 2

Sample Output:

YES

NO

NO

YES

NO

 1 #include <stdio.h>
 2 #define N 1000
 3 int main()  4 {  5     int m,n,k;//m棧的最大容量, n壓棧元素個數, k行測試數列
 6     scanf("%d%d%d", &m, &n, &k);  7     for(int i=0; i<k; i++)//k行測試數列
 8  {  9         int stack[N]; //
10         int top = -1; 11         int arr[N];   //數列數組
12         for(int j=0; j<n; j++)//輸入一個數列
13             scanf("%d", &arr[j]); 14         int count = 0; //相同個數(做爲arr下標)
15         for(int j=1; j<=n; j++)//從數字1開始壓棧
16  { 17             stack[++top] = j;//壓棧
18             if(top + 1 > m)//第一個棧元素下標爲0
19                 break; 20             while(top != -1 && stack[top]==arr[count]) 21  { 22                 top--; 23                 count++; 24  } 25  } 26         if(count == n) 27             printf("YES\n"); 28         else
29             printf("NO\n"); 30  } 31     return 0; 32 }

03-1 樹的同構

給定兩棵樹T1T2。若是T1能夠經過若干次左右孩子互換就變成T2,則咱們稱兩棵樹是「同構」的。例如圖1給出的兩棵樹就是同構的,由於咱們把其中一棵樹的結點ABG的左右孩子互換後,就獲得另一棵樹。而圖2就不是同構的。

 

1

 

 

2

現給定兩棵樹,請你判斷它們是不是同構的。

輸入格式:

輸入給出2棵二叉樹樹的信息。對於每棵樹,首先在一行中給出一個非負整數N (10),即該樹的結點數(此時假設結點從0N−1編號);隨後N行,第i行對應編號第i個結點,給出該結點中存儲的1個英文大寫字母、其左孩子結點的編號、右孩子結點的編號。若是孩子結點爲空,則在相應位置上給出「-」。給出的數據間用一個空格分隔。注意:題目保證每一個結點中存儲的字母是不一樣的。

輸出格式:

若是兩棵樹是同構的,輸出「Yes」,不然輸出「No」。

輸入樣例1(對應圖1):

8

A 1 2

B 3 4

C 5 -

D - -

E 6 -

G 7 -

F - -

H - -

8

G - 4

B 7 6

F - -

A 5 1

H - -

C 0 -

D - -

E 2 -  

輸出樣例1:

Yes

輸入樣例2(對應圖2):

8

B 5 7

F - -

A 0 3

C 6 -

H - -

D - -

G 4 -

E 1 -

8

D 6 -

B 5 -

E - -

H - -

C 0 2

G - 3

F - -

A 1 4  

輸出樣例2:

No

 1 #include <stdio.h>
 2 #include <malloc.h>
 3 #define null -1
 4 /* 定義樹結點 */
 5 struct TreeNode{  6     char data;  // 存值 
 7     int left;   // 左子樹的下標 
 8     int right;  // 右子樹的下標 
 9 }T1[10],T2[10]; 10 
11 /* 構造樹並返回根結點 */
12 int create(struct TreeNode T[]) 13 { 14     int n; 15     int root = 0; 16     char left, right; 17     /* 輸入結點數 */
18     scanf("%d", &n); 19     /* 空樹 */
20     if(!n) 21         return null; 22     for(int i=0;i<n;i++) 23  { 24         root +=i;  /* 累加i*/  
25         /* 輸入數據 */
26         scanf(" %c %c %c", &T[i].data, &left, &right); 27         /* 1.left */
28         if(left=='-') 29             T[i].left = null; 30         else{ 31             T[i].left = left-'0'; 32             root -= T[i].left; //
33  } 34         /* 2.right */
35         if(right=='-') 36             T[i].right = null; 37         else{ 38             T[i].right = right-'0'; 39             root -= T[i].right;//
40  } 41  } 42     return root; 43 } 44 /* 判斷是否同構 */
45 int judge(int R1,int R2) 46 { 47     /* 1.兩棵樹都爲空 */
48     if(R1 == null && R2 == null) 49         return 1; 50     /* 2.一個爲空,一個不爲空 */
51     if(R1 == null && R2 != null || R1 != null && R2 == null) 52         return 0; 53     /* 3.兩顆樹的值不一樣 */
54     if(T1[R1].data != T2[R2].data) 55         return 0; 56     /* 4.左兒子爲空*/
57     if(T1[R1].left == null && T2[R2].left == null) 58         return judge(T1[R1].right,T2[R2].right); 59     /* 5.左兒子不爲空且值相等*/
60     if((T1[R1].left != null && T2[R2].left != null ) 61                             &&(T1[T1[R1].left].data == T2[T2[R2].left].data)) 62         return judge(T1[R1].left,T2[R2].left) 63                             &&judge(T1[R1].right,T2[R2].right); 64     /* 6.左兒子不爲空且值不等 或者 某一個樹的左兒子爲空*/
65     else   
66         return judge(T1[R1].right,T2[R2].left) 67             && judge(T1[R1].left,T2[R2].right); 68 } 69 int main() 70 { 71     int R1,R2; 72     R1 = create(T1); 73     R2 = create(T2); 74     if(judge(R1,R2)) 75         printf("Yes"); 76     else
77         printf("No"); 78     return 0; 79 }

03-樹2 List Leaves

Given a tree, you are supposed to list all the leaves in the order of top down, and left to right.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤10) which is the total number of nodes in the tree -- and hence the nodes are numbered from 0 to N−1. Then N lines follow, each corresponds to a node, and gives the indices of the left and right children of the node. If the child does not exist, a "-" will be put at the position. Any pair of children are separated by a space.

Output Specification:

For each test case, print in one line all the leaves' indices in the order of top down, and left to right. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.

Sample Input:

8

1 -

- -

0 -

2 7

- -

- -

5 -

4 6

Sample Output:

4 1 5

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <malloc.h>
 4 #include <stdbool.h>
 5 
 6 /* 定義樹結構(順序存儲) */
 7 #define null -1 //-1 表示空
 8 struct TreeNode{  9     int data;   // 數據 0~N-1
 10     int left;   // 左兒子下標
 11     int right;  // 右兒子下標
 12 }T[10]; //最大10個結點
 13 
 14 /* 順序循環隊列(隊頭指針在第一個元素前)*/
 15 #define MAXSIZE  10 //最大隊列長度 N 
 16 typedef int Position; //隊列的頭\尾指針類型
 17 typedef struct TreeNode ElementType; //隊列元素類型 
 18 typedef struct QNode *Queue;  19 struct QNode {  20     ElementType *Data;     /* 存儲元素的數組 */
 21     Position Front, Rear;  /* 隊列的頭、尾指針 */
 22     int MaxSize;           /* 隊列最大容量 */
 23 };  24 
 25  /* 建隊列 */
 26 Queue CreateQueue( int MaxSize )//返回隊列指針
 27 {  28     Queue Q = (Queue)malloc(sizeof(struct QNode));  29     Q->Data = (ElementType *)malloc(MaxSize * sizeof(ElementType));  30     Q->Front = Q->Rear = 0;  31     Q->MaxSize = MaxSize;  32     return Q;  33 }  34 
 35 /* 隊滿 */
 36 bool IsFull( Queue Q )  37 {  38     return ((Q->Rear+1)%Q->MaxSize == Q->Front);  39 }  40 
 41 /* 隊空 */
 42 bool IsEmpty( Queue Q )  43 {  44     return (Q->Front == Q->Rear);  45 }  46 
 47 /* 入隊 */
 48 bool AddQ( Queue Q, ElementType X )  49 {  50     if ( IsFull(Q) ) {  51         return false;  52  }  53     else {  54         Q->Rear = (Q->Rear+1)%Q->MaxSize;  55         Q->Data[Q->Rear] = X;  56         return true;  57  }  58 }  59 
 60 /* 出隊 */
 61 ElementType* DeleteQ( Queue Q )  62 {  63     if ( IsEmpty(Q) )  64         return NULL;  65     Q->Front =(Q->Front+1)%Q->MaxSize;  66     return  &Q->Data[Q->Front];  67 }  68 
 69 // 樹結點輸入
 70 int create()  71 {  72     int n;  73     int root = 0;  74     char left, right;  75     
 76     scanf("%d", &n);  77     if(!n) //結點數爲0, 返回空(-1)
 78         return null;  79     
 80     for(int i=0; i<n; i++)  81  {  82         root += i;//累加
 83         T[i].data = i; //數據0~N-1
 84         
 85         scanf(" %c %c", &left, &right);  86         
 87         if(left=='-')//左兒子下標
 88             T[i].left = null;  89         else{  90             T[i].left = left-'0';  91             root -= T[i].left;//
 92  }  93         
 94         if(right=='-')//右兒子下標
 95             T[i].right = null;  96         else{  97             T[i].right = right-'0';  98             root -= T[i].right;//
 99  } 100  } 101     return root; 102 } 103 
104 // 層序遍歷(從上到下從左到右) 
105 void LevelorderTraversal(int root) 106 { 107     if(root == null){ 108         printf("-");// 樹爲空,輸出"-"
109         return; 110  } 111     
112     Queue q = CreateQueue(MAXSIZE);//建隊列(指針)
113     bool flag = false; //控制空格輸出
114     AddQ(q, T[root]); //樹根入隊
115     
116     while(!IsEmpty(q)) 117  { 118         ElementType* t = DeleteQ(q);// 出隊, 返回隊首元素
119         
120         if(t->left == null && t->right == null) 121         {  //若是爲葉子結點就輸出 
122             if(flag) 123                 printf(" "); 124             else
125                 flag = true; 126             printf("%d", t->data); 127  } 128         
129         if(t->left != null)  // 有左兒子入隊
130             AddQ(q, T[t->left]); 131         if(t->right != null)  // 有右兒子入隊
132             AddQ(q, T[t->right]); 133  } 134 } 135  
136 int main() 137 { 138     int root = create(); 139  LevelorderTraversal(root); 140     return 0; 141 }

03-樹3 Tree Traversals Again

An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: "Push X" where X is the index of the node being pushed onto the stack; or "Pop" meaning to pop one node from the stack.

Output Specification:

For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

  Figure 1

Sample Input:

6

Push 1

Push 2

Push 3

Pop

Pop

Push 4

Pop

Pop

Push 5

Push 6

Pop

Pop

Sample Output:

3 4 2 6 5 1

 1 #include <stdio.h>
 2 #include <stdlib.h> //atoi
 3 #include <string.h> //strcmp
 4 
 5 #define N 31
 6 typedef int ElementType;  7 typedef struct TreeNode *Tree;//樹類型
 8 struct TreeNode{  9     ElementType data;  // 數字 1 ~ N
10     Tree left;         // 左子樹 
11     Tree right;        // 右子樹 
12 }; 13 
14 typedef Tree Stack;//樹棧類型 15 
16 //先序遍歷建樹 
17 Tree PreorderTraversal() 18 { 19     Tree T = (Tree)malloc(sizeof(struct TreeNode)); 20     T->left = NULL; 21     T->right = NULL; //樹根
22     Tree t = T; 23     
24     Stack s[N];    //樹棧
25     int top = -1; 26     
27     int n; 28     scanf("%d\n",&n); 29     
30     char str[N];   //字符串 
31  gets(str); 32     
33     t->data = atoi(&str[5]); // 根節點data 
34     s[++top] = t;            //根結點入棧 
35 
36     for(int i=1; i<2*n; i++) //2N lines
37  { 38         gets(str);              //逐行讀取
39         if(!strcmp(str,"Pop")){ //Pop
40             t = s[top];         //出棧指針
41             top--; 42         }else{                  // Push 
43             Tree tmp  = (Tree)malloc(sizeof(struct TreeNode)); 44             tmp->left = NULL; 45             tmp->right = NULL; 46             tmp->data = atoi(&str[5]); //樹結點data 
47             s[++top] = tmp;     //新結點入棧
48             
49             if(!t->left){       // 左插
50                 t->left = tmp; 51                 t = t->left; 52             }else if(!t->right){ //右插
53                 t->right = tmp; 54                 t = t->right; 55  } 56  } 57  } 58     return T; 59 } 60 
61 // 後序遞歸遍歷
62 void PostorderTraversal(Tree T, int *flag) 63 { 64     if(T){ 65         PostorderTraversal(T->left,flag); 66         PostorderTraversal(T->right,flag); 67         if(!(*flag)) 68             *flag = 1; 69         else
70             printf(" "); 71         printf("%d", T->data); 72  } 73 } 74 
75 int main() 76 { 77     Tree T = PreorderTraversal(); //先序建樹
78     int flag = 0; 79     PostorderTraversal(T,&flag); //後序輸出
80     return 0; 81 }

04-樹7 二叉搜索樹的操做集

本題要求實現給定二叉搜索樹的5種經常使用操做。

函數接口定義:

BinTree Insert( BinTree BST, ElementType X ); BinTree Delete( BinTree BST, ElementType X ); Position Find( BinTree BST, ElementType X ); Position FindMin( BinTree BST ); Position FindMax( BinTree BST );

其中BinTree結構定義以下:

typedef struct TNode *Position; typedef Position BinTree; struct TNode{ ElementType Data; BinTree Left; BinTree Right; };

函數Insert將X插入二叉搜索樹BST並返回結果樹的根結點指針;

函數Delete將X從二叉搜索樹BST中刪除,並返回結果樹的根結點指針;若是X不在樹中,則打印一行Not Found並返回原樹的根結點指針;

函數Find在二叉搜索樹BST中找到X,返回該結點的指針;若是找不到則返回空指針;

函數FindMin返回二叉搜索樹BST中最小元結點的指針;

函數FindMax返回二叉搜索樹BST中最大元結點的指針。

#include <stdio.h> #include <stdlib.h> typedef int ElementType; typedef struct TNode *Position; typedef Position BinTree; struct TNode{ ElementType Data; BinTree Left; BinTree Right; }; void PreorderTraversal( BinTree BT ); /* 先序遍歷,由裁判實現,細節不表 */
void InorderTraversal( BinTree BT );  /* 中序遍歷,由裁判實現,細節不表 */ BinTree Insert( BinTree BST, ElementType X ); BinTree Delete( BinTree BST, ElementType X ); Position Find( BinTree BST, ElementType X ); Position FindMin( BinTree BST ); Position FindMax( BinTree BST ); int main() { BinTree BST, MinP, MaxP, Tmp; ElementType X; int N, i; BST = NULL; scanf("%d", &N); for ( i=0; i<N; i++ ) { scanf("%d", &X); BST = Insert(BST, X); } printf("Preorder:"); PreorderTraversal(BST); printf("\n"); MinP = FindMin(BST); MaxP = FindMax(BST); scanf("%d", &N); for( i=0; i<N; i++ ) { scanf("%d", &X); Tmp = Find(BST, X); if (Tmp == NULL) printf("%d is not found\n", X); else { printf("%d is found\n", Tmp->Data); if (Tmp==MinP) printf("%d is the smallest key\n", Tmp->Data); if (Tmp==MaxP) printf("%d is the largest key\n", Tmp->Data); } } scanf("%d", &N); for( i=0; i<N; i++ ) { scanf("%d", &X); BST = Delete(BST, X); } printf("Inorder:"); InorderTraversal(BST); printf("\n"); return 0; } /* 你的代碼將被嵌在這裏 */

輸入樣例:

10
5 8 6 2 4 1 0 10 9 7
5
6 3 10 0 5
5
5 7 0 10 3

輸出樣例:

Preorder: 5 2 1 0 4 8 6 7 10 9
6 is found 3 is not found 10 is found 10 is the largest key 0 is found 0 is the smallest key 5 is found Not Found Inorder: 1 2 4 6 8 9
 1 // 插入 
 2 BinTree Insert( BinTree BST, ElementType X ){  3     if(!BST){  // 若是爲空,建立新結點 
 4         BST = (BinTree)malloc(sizeof(struct TNode));  5         BST->Data = X;  6         BST->Left = NULL;  7         BST->Right = NULL;  8     }else{  9         if(X < BST->Data) 10             BST->Left = Insert(BST->Left,X); 11         else if(BST->Data < X) 12             BST->Right = Insert(BST->Right,X); 13  } 14     return BST; 15 } 16 
17 // 刪除
18 BinTree Delete( BinTree BST, ElementType X ){ 19  BinTree tmp; 20     if(!BST){ 21         printf("Not Found\n"); 22         return BST; 23     }else{ 24         if(X < BST->Data) 25             BST->Left = Delete(BST->Left,X); 26         else if(BST->Data < X) 27             BST->Right = Delete(BST->Right,X); 28         else{  // 找到要刪除結點 
29             if(BST->Left && BST->Right){  // 若是該結點有左右兒子 
30                 tmp = FindMin(BST->Right); 31                 BST->Data = tmp->Data; 32                 BST->Right = Delete(BST->Right,tmp->Data); 33             }else{ 34                 tmp = BST; 35                 if(BST->Left && !BST->Right) 36                     BST = BST->Left; 37                 else if(!BST->Left && BST->Right) 38                     BST = BST->Right; 39                 else
40                     BST = NULL; 41                 free(tmp); 42  } 43  } 44  } 45     return BST; 46 } 47 
48 // 尋找值最小結點 
49 Position FindMin( BinTree BST ){ 50     if(BST) 51         while(BST->Left) 52             BST = BST->Left; 53     return BST; 54 } 55 
56 // 尋找值最大結點
57 Position FindMax( BinTree BST ){ 58     if(BST) 59         while(BST->Right) 60             BST = BST->Right; 61     return BST; 62 } 63 
64 // 查找
65 Position Find( BinTree BST, ElementType X ){ 66     if(!BST){ 67         return NULL; 68     }else if(X < BST->Data) 69         return Find(BST->Left,X); 70     else if(BST->Data < X) 71         return Find(BST->Right,X); 72     else
73         return BST; 74 }

04-樹4 是否同一棵二叉搜索樹 

給定一個插入序列就能夠惟一肯定一棵二叉搜索樹。然而,一棵給定的二叉搜索樹卻能夠由多種不一樣的插入序列獲得。例如分別按照序列{2, 1, 3}和{2, 3, 1}插入初始爲空的二叉搜索樹,都獲得同樣的結果。因而對於輸入的各類插入序列,你須要判斷它們是否能生成同樣的二叉搜索樹。 

輸入格式:

輸入包含若干組測試數據。每組數據的第1行給出兩個正整數N (≤10)和L,分別是每一個序列插入元素的個數和須要檢查的序列個數。第2行給出N個以空格分隔的正整數,做爲初始插入序列。最後L行,每行給出N個插入的元素,屬於L個須要檢查的序列。

簡單起見,咱們保證每一個插入序列都是1到N的一個排列。當讀到N爲0時,標誌輸入結束,這組數據不要處理。

輸出格式:

對每一組須要檢查的序列,若是其生成的二叉搜索樹跟對應的初始序列生成的同樣,輸出「Yes」,不然輸出「No」。

輸入樣例:

4 2
3 1 4 2
3 4 1 2
3 2 4 1
2 1
2 1
1 2
0

輸出樣例:

Yes No No
 1 #include <stdio.h>
 2 #include <malloc.h>
 3 /* 樹結點定義 */
 4 typedef struct TreeNode *Tree;  5 struct TreeNode {  6     int v;  7  Tree Left, Right;  8     int flag; /* 判別結點是否訪問過的標記 */
 9 };  10 
 11 /* 函數聲明  12  1.建立一個樹結點  13  2.插入一個樹結點  14  3.建立一棵樹  15  4.檢查樹結點是否訪問過  16  5.判斷是否同一棵樹  17  6.清除樹中各結點的flag標記  18  7.釋放樹的空間  19 */
 20 Tree NewNode( int V );  21 Tree Insert( Tree T, int V );  22 Tree MakeTree( int N );  23 int check ( Tree T, int V );  24 int Judge( Tree T, int N );  25 void ResetT ( Tree T );  26 void FreeTree ( Tree T );  27 
 28 /* 主程序 */
 29 int main()  30 {  31     int N, L, i;  32     Tree T; /* 建立一個樹的空結點 */
 33     scanf("%d", &N);  34     while (N)  35  {  36         scanf("%d", &L);  37         T = MakeTree(N); /* 建立一棵N個結點的樹 */
 38         for (i=0; i<L; i++)  39         {   /* 判斷是否同一棵樹 */
 40             if (Judge(T, N)) printf("Yes\n");  41             else printf("No\n");  42             ResetT(T); /*清除T中的標記flag*/
 43  }  44         FreeTree(T); /* 釋放上面的樹空間 */
 45         scanf("%d", &N);  46  }  47     return 0;  48 }  49 /* 建立一個樹結點 */
 50 Tree NewNode( int V )  51 {  52     Tree T = (Tree)malloc(sizeof(struct TreeNode));  53     T->v = V;  54     T->Left = T->Right = NULL;  55     T->flag = 0;  56     return T;  57 }  58 /* 插入一個樹結點 */
 59 Tree Insert( Tree T, int V )  60 {  61     if ( !T ) T = NewNode(V);  62     else 
 63  {  64         if ( V > T->v )  65             T->Right = Insert( T->Right, V );  66         else
 67             T->Left = Insert( T->Left, V );  68  }  69     return T;  70 }  71 /* 建立一棵N個結點的樹 */
 72 Tree MakeTree( int N )  73 {  74  Tree T;  75     int i, V;  76     scanf("%d", &V);  77     T = NewNode(V); /*  */
 78     for (i=1; i<N; i++)  79  {  80         scanf("%d", &V);  81         T = Insert(T, V); /*  */
 82  }  83     return T;  84 }  85 /* 判斷樹的結點是否訪問過 */
 86 int check ( Tree T, int V )  87 {  88     if ( T->flag )  89  {  90         if ( V<T->v ) return check(T->Left, V);  91         else if ( V>T->v ) return check(T->Right, V);  92         else return 0;  93  }  94     else 
 95  {  96         if ( V==T->v )  97  {  98             T->flag = 1;  99             return 1; 100  } 101         else return 0; 102  } 103 } 104 /* 判斷是否同一棵樹 */
105 int Judge( Tree T, int N ) 106 { 107     int i, V, flag = 0; 108     /* flag, 0表明目前還一致, 1表明已經不一致*/
109     scanf("%d", &V); 110     if ( V!=T->v ) flag = 1; 111     else T->flag = 1; 112     for (i=1; i<N; i++) 113  { 114         scanf("%d", &V);/* 讀取結點的V */
115         if ( (!flag) && (!check(T, V)) ) flag = 1; 116  } 117     return !flag; /* 1表明已經不一致 */
118 } 119 /* 清除T中各結點的flag標記 */
120 void ResetT ( Tree T ) 121 { 122     if (T->Left) ResetT(T->Left); 123     if (T->Right) ResetT(T->Right); 124     T->flag = 0; 125 } 126 /* 釋放T的空間 */
127 void FreeTree ( Tree T ) 128 { 129     if (T->Left) FreeTree(T->Left); 130     if (T->Right) FreeTree(T->Right); 131     free(T); 132 }

04-樹5 Root of AVL Tree

An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.

 

 

Now given a sequence of insertions, you are supposed to tell the root of the resulting AVL tree.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤20) which is the total number of keys to be inserted. Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the root of the resulting AVL tree in one line.

Sample Input 1:

5
88 70 61 96 120

Sample Output 1:

70

Sample Input 2:

7
88 70 61 96 120 90 65

Sample Output 2:

88
 1 #include <stdio.h>
 2 #include <malloc.h>
 3 
 4 typedef int ElementType;  5 typedef struct AVLNode *Position;  6 typedef Position AVLTree; /* AVL樹類型 */
 7 struct AVLNode{  8     ElementType Data; /* 結點數據 */
 9     AVLTree Left;     /* 指向左子樹 */
 10     AVLTree Right;    /* 指向右子樹 */
 11     int Height;       /* 樹高 */
 12 };  13 
 14 /* AVL樹左右單旋\左右雙旋\右左雙旋\插入 */
 15 int GetHeight( AVLTree A ); /* 樹高 */
 16 int Max ( int a, int b );   /* 結點數據大小 */
 17 AVLTree SingleLeftRotation ( AVLTree A );  18 AVLTree SingleRightRotation ( AVLTree A );  19 AVLTree DoubleLeftRightRotation ( AVLTree A );  20 AVLTree DoubleRightLeftRotation ( AVLTree A );  21 AVLTree Insert( AVLTree T, ElementType X );  22  
 23 /* 主程序 */
 24 int main()  25 {  26     AVLTree AVLT = NULL;  27     int N, i;  28  ElementType X;  29     scanf("%d", &N);  30     for ( i=0; i<N; i++ ) {  31         scanf("%d", &X);  32         AVLT = Insert(AVLT, X);  33  }  34     printf("%d\n", AVLT->Data);  35     return 0;  36 }  37 
 38 /* 樹高 */
 39 int GetHeight(AVLTree A)  40 {  41     if(!A) return -1;  42     return A->Height;  43 }  44 
 45 /* 樹數據大小 */
 46 int Max ( int a, int b )  47 {  48     return a > b ? a : b;  49 }  50 
 51 /* 左單旋 */
 52 AVLTree SingleLeftRotation ( AVLTree A )  53 { /* 注意:A必須有一個左子結點B */
 54   /* 將A與B作左單旋,更新A與B的高度,返回新的根結點B */     
 55  
 56     AVLTree B = A->Left;  57     A->Left = B->Right;  58     B->Right = A;  59     A->Height = Max( GetHeight(A->Left), GetHeight(A->Right) ) + 1;  60     B->Height = Max( GetHeight(B->Left), A->Height ) + 1;  61   
 62     return B;  63 }  64 
 65 /* 右單旋 */
 66 AVLTree SingleRightRotation ( AVLTree A )  67 { /* 注意:A必須有一個右子結點B */
 68   /* 將A與B作右單旋,更新A與B的高度,返回新的根結點B */     
 69  
 70     AVLTree B = A->Right;  71     A->Right = B->Left;  72     B->Left = A;  73     A->Height = Max( GetHeight(A->Left), GetHeight(A->Right) ) + 1;  74     B->Height = Max( GetHeight(B->Left), A->Height ) + 1;  75   
 76     return B;  77 }  78 
 79 /* 左右雙旋 */
 80 AVLTree DoubleLeftRightRotation ( AVLTree A )  81 { /* 注意:A必須有一個左子結點B,且B必須有一個右子結點C */
 82   /* 將A、B與C作兩次單旋,返回新的根結點C */
 83      
 84     /* 將B與C作右單旋,C被返回 */
 85     A->Left = SingleRightRotation(A->Left);  86     /* 將A與C作左單旋,C被返回 */
 87     return SingleLeftRotation(A);  88 }  89 
 90 /* 右左雙旋 */
 91 AVLTree DoubleRightLeftRotation ( AVLTree A )  92 { /* 注意:A必須有一個右子結點B,且B必須有一個左子結點C */
 93   /* 將A、B與C作兩次單旋,返回新的根結點C */
 94      
 95     /* 將B與C作右單旋,C被返回 */
 96     A->Right = SingleLeftRotation(A->Right);  97     /* 將A與C作右單旋,C被返回 */
 98     return SingleRightRotation(A);  99 } 100 
101 /* 插入 */
102 AVLTree Insert( AVLTree T, ElementType X ) 103 { /* 將X插入AVL樹T中,而且返回調整後的AVL樹 */
104     if ( !T ) { /* 若插入空樹,則新建包含一個結點的樹 */
105         T = (AVLTree)malloc(sizeof(struct AVLNode)); 106         T->Data = X; 107         T->Height = 0; 108         T->Left = T->Right = NULL; 109     } /* if (插入空樹) 結束 */
110  
111     else if ( X < T->Data ) { 112         /* 插入T的左子樹 */
113         T->Left = Insert( T->Left, X); 114         /* 若是須要左旋 */
115         if ( GetHeight(T->Left)-GetHeight(T->Right) == 2 ) 116             if ( X < T->Left->Data ) 117                T = SingleLeftRotation(T);      /* 左單旋 */
118             else 
119                T = DoubleLeftRightRotation(T); /* 左-右雙旋 */
120     } /* else if (插入左子樹) 結束 */
121      
122     else if ( X > T->Data ) { 123         /* 插入T的右子樹 */
124         T->Right = Insert( T->Right, X ); 125         /* 若是須要右旋 */
126         if ( GetHeight(T->Left)-GetHeight(T->Right) == -2 ) 127             if ( X > T->Right->Data ) 128                T = SingleRightRotation(T);     /* 右單旋 */
129             else 
130                T = DoubleRightLeftRotation(T); /* 右-左雙旋 */
131     } /* else if (插入右子樹) 結束 */
132  
133     /* else X == T->Data,無須插入 */
134  
135     /* 別忘了更新樹高 */
136     T->Height = Max( GetHeight(T->Left), GetHeight(T->Right) ) + 1; 137      
138     return T; 139 }

04-樹6 Complete Binary Search Tree 

A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

The left subtree of a node contains only nodes with keys less than the node's key.

The right subtree of a node contains only nodes with keys greater than or equal to the node's key.

Both the left and right subtrees must also be binary search trees.

A Complete Binary Tree (CBT) is a tree that is completely filled, with the possible exception of the bottom level, which is filled from left to right.

Now given a sequence of distinct non-negative integer keys, a unique BST can be constructed if it is required that the tree must also be a CBT. You are supposed to output the level order traversal sequence of this BST.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤1000). Then N distinct non-negative integer keys are given in the next line. All the numbers in a line are separated by a space and are no greater than 2000.

Output Specification:

For each test case, print in one line the level order traversal sequence of the corresponding complete binary search tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.

Sample Input:

10

1 2 3 4 5 6 7 8 9 0

Sample Output:

6 3 8 1 5 7 9 0 2 4

 1 #include <stdio.h>
 2 #include <math.h>
 3 
 4 #define MaxSize 2001
 5 int value[MaxSize]; /* BST樹 */
 6 int BST[MaxSize];   /* 徹底二叉樹 */
 7 
 8 /* 計算 n 個結點的樹其左樹結點個數 */ 
 9 int getLeftTreeSize(int n) 10 { 11     int h = 0;   /* 0.保存該結點下滿二叉樹的層數 */ 
12     int tmp = n+1;    /* n+1, 結點爲1的狀況下,1+1除以2結果爲1 */
13     while( tmp != 1 ) 14  { 15         tmp /= 2; /* 每層比上一層多2倍, 除以2就是一層 */
16         h++; 17  } 18     /* 1.最下面一排葉結點個數 */ 
19     int x = n - (pow(2,h)-1); 20     /* 2.左子樹的葉結點個數最可能是 2^(h-1) 21  若是最下一排葉結點含有右樹葉結點,即大於2^(h-1) 22  取左子樹最大葉結點數2^(h-1) */
23     x = x<pow(2,h-1) ? x: pow(2,h-1); 24     /* 3.左子樹的個數 */ 
25     int L = pow(2,h-1)-1 + x; 26     /* 
27  左滿樹 + 左葉子結點 == 左子樹的結點數, 28  左滿樹 比 根滿樹 低一層 pow(2,h-1)-1 29  根滿樹pow(2,h)-1 30  根滿樹 + 最下面一排葉子結點數 == n 31     */
32     return L; 33 } 34 
35 /* 填充函數 */
36 void fill(int left,int right,int root) 37 { 38     int n = right - left + 1;  // 肯定範圍內數值個數 
39      if(!n) 40          return; 41      int L = getLeftTreeSize(n);   // 找到"偏移量" 
42      BST[root] = value[left + L];  // 根結點的值 左邊界值 + 偏移量 
43      int leftRoot = 2 * root + 1;   // 左兒子結點位置,因爲從 0 開始 
44      int rightRoot = leftRoot + 1;  // 右兒子結點位置 
45      fill(left, left+L-1, leftRoot);    // 左子樹遞歸 
46      fill(left+L+1, right, rightRoot);  // 右子樹遞歸 
47 } 48 
49 void QuickSort(int *a, int n, int left, int right) 50 { 51     int i, j, t; 52         /*左指針left指向數組頭 右指針right指向數組尾*/
53     if(left<right) 54  { 55         i = left, j = right+1;/*左右指針*/
56         while(i<j) 57  { 58             while(i+1<n && a[++i]<a[left]);/*左指針右移 指向大於基數的數據中止*/
59             while(j-1>-1 && a[--j]>a[left]);/*右指針左移 指向小於基數的數據中止*/
60             if(i<j)/*知足左指針小於右指針的條件 兩指針指向數據交換*/
61                 t = a[i], a[i] = a[j], a[j] = t; 62  } 63         t = a[left], a[left] = a[j], a[j] = t;/*右指針指向數據與基數交換*/
64         QuickSort(a, n, left, j-1);/*左邊數據遞歸*/
65         QuickSort(a, n, j+1, right);/*右邊數據遞歸*/
66  } 67 } 68 
69 int main() 70 { 71     int n; 72     scanf("%d", &n); 73     for(int i=0;i<n;i++) 74         scanf("%d", &value[i]); 75     /* BST樹左小右大的屬性 */
76     QuickSort( value, n, 0, n-1 ); /* 從小到大排序 */
77     fill( 0, n-1, 0 ); /* 徹底二叉樹填充,下標從0開始 */
78     for(int i=0;i<n;i++) 79  { 80         if(i) 81             printf(" "); 82         printf("%d", BST[i]); 83  } 84     return 0; 85 }

05-樹7 堆中的路徑

將一系列給定數字插入一個初始爲空的小頂堆H[]。隨後對任意給定的下標i,打印從H[i]到根結點的路徑。

輸入格式:

每組測試第1行包含2個正整數N和M(≤1000),分別是插入元素的個數、以及須要打印的路徑條數。下一行給出區間[-10000, 10000]內的N個要被插入一個初始爲空的小頂堆的整數。最後一行給出M個下標。

輸出格式:

對輸入中給出的每一個下標i,在一行中輸出從H[i]到根結點的路徑上的數據。數字間以1個空格分隔,行末不得有多餘空格。

輸入樣例:

5 3

46 23 26 24 10

5 4 3

輸出樣例:

24 23 10

46 23 10

26 10

 1 #include <stdio.h>
 2 
 3 /* 1.定義堆H */
 4 #define MAXN 1001
 5 #define MINH -10001
 6 int H[MAXN], size;  7 
 8 /* 2.堆的初始化 */
 9 void Create () 10 { 11     size = 0; 12     H[0] = MINH; 13 } 14 
15 /* 3.堆插入 */
16 void Insert ( int X ) 17 { 18     int i; 19     for (i=++size; H[i/2] > X; i/=2) 20         H[i] = H[i/2]; 21     H[i] = X; 22 } 23 
24 int main() 25 { 26     int n, m, x, i, j; 27     scanf("%d%d", &n, &m); 28  Create(); 29     for (i=0; i<n; i++) { 30         scanf("%d", &x); 31  Insert(x); 32  } 33         
34     for (i=0; i<m; i++) 35  { 36         scanf("%d", &j); 37         printf("%d", H[j]); 38         while (j>1) { 39             j /= 2; 40             printf(" %d", H[j]); 41  } 42         printf("\n"); 43  } 44     return 0; 45 }

05-樹8 File Transfer

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:

I c1 c2 

where I stands for inputting a connection between c1 and c2; or

C c1 c2   

where C stands for checking if it is possible to transfer files between c1 and c2; or

S

where S stands for stopping this case.

Output Specification:

For each C case, print in one line the word "yes" or "no" if it is possible or impossible to transfer files between c1 and c2, respectively. At the end of each case, print in one line "The network is connected." if there is a path between any pair of computers; or "There are k components." where k is the number of connected components in this network.

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.

 1 #include <stdio.h>
 2  
 3 /* 集合的簡化 */
 4 #define MaxSize 10001 
 5 typedef int ElementType; /*默認元素能夠用非負整數表示*/
 6 typedef int SetName; /*默認用根結點的下標做爲集合名稱*/
 7 typedef ElementType SetType[MaxSize];/* 定義集合類型 */
 8 
 9 /* Initialization */
10 void Initialization( SetType S , int n ) 11 { 12     int i; 13     for ( i=0; i<n; i++ ) S[i] = -1; 14 } 15 
16 /* find */
17 SetName Find( SetType S, ElementType X ) 18 { 19     if ( S[X] < 0 ) /* 找到集合的根 */
20         return X; 21     else    
22         return S[X] = Find( S, S[X] ); 23 } 24 
25 /* union */
26 void Union( SetType S, SetName Root1, SetName Root2 ) 27 {     /* 按規模 比元素個數,少的貼多的 */
28     if ( S[Root2]<S[Root1] ){ //負數,小即多
29         S[Root2] += S[Root1]; 30         S[Root1] = Root2; 31  } 32     else { 33         S[Root1] += S[Root2]; 34         S[Root2] = Root1; 35  } 36 } 37 
38 /* input */
39 void Input_connection( SetType S ) 40 { 41  ElementType u, v; 42  SetName Root1, Root2; 43     scanf("%d %d\n", &u, &v); 44     Root1 = Find(S, u-1); 45     Root2 = Find(S, v-1); 46     if ( Root1 != Root2 ) 47  Union( S, Root1, Root2 ); 48 } 49 
50 /* check connection */
51 void Check_connection( SetType S ) 52 { 53  ElementType u, v; 54  SetName Root1, Root2; 55     scanf("%d %d\n", &u, &v); 56     Root1 = Find(S, u-1); 57     Root2 = Find(S, v-1); 58     if ( Root1 == Root2 ) 59         printf("yes\n"); 60     else printf("no\n"); 61 } 62 
63 /* check network */
64 void Check_network( SetType S, int n ) 65 { 66     int i, counter = 0; 67     for (i=0; i<n; i++) { 68         if ( S[i] < 0 ) counter++; 69  } 70     if ( counter == 1 ) 71         printf("The network is connected.\n"); 72     else
73         printf("There are %d components.\n", counter); 74 } 75 
76 /* 測試 */
77 int main() 78 { 79  SetType S; 80     int n; 81     char in; 82     scanf("%d\n", &n); 83  Initialization( S, n ); 84     do { 85         scanf("%c", &in); 86         switch (in) { 87             case 'I': Input_connection( S ); break; 88             case 'C': Check_connection( S ); break; 89             case 'S': Check_network( S, n ); break; 90  } 91     } while ( in != 'S'); 92     return 0; 93 }

05-樹9 Huffman Codes

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.

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
 1 /* 
 2  建一個最小堆, 堆插入樹結點, 造成樹結點森林;  3  每次從堆中取2個最小樹結點, 建中間樹結點並插入堆;  4  最後堆中森林造成一棵Huffman樹並計算WPL;  5  判斷前綴碼\結點數\WPL, 肯定編碼是否正確;  6 */
 7 
 8 #include <stdio.h>
 9 #include <stdlib.h>
 10 #include <string.h>
 11 
 12 /* 二叉樹結點 */
 13 typedef struct TreeNode* Tree;  14 struct TreeNode {  15     int Weight;  16  Tree Left, Right;  17 };  18 
 19 /* 堆(優先隊列) */
 20 #define MAXSIZE 256 
 21 typedef struct HeapNode* Heap;  22 struct HeapNode {  23     struct TreeNode Data[MAXSIZE];/* 徹底二叉樹順序存儲 */
 24     int Size;  25 };  26  
 27 Tree NewTreeNode();/* 建樹結點 */
 28 Heap CreatHeap(); /* 建空堆 */
 29 void Insert(Heap H, struct TreeNode T);/* 堆插入 */
 30 Tree Delete(Heap H);/* 堆刪除 */
 31 Tree Huffman(Heap H); /* 建Huffman樹 */
 32 int WPL(Tree T, int Depth);/* 整棵樹的WPL */
 33 
 34 int Judge(int codelen, int Weight[], int N) ; /* 判斷是否正確的Huffman編碼 */
 35 
 36 int main()  37 {  38     int N, Weight[MAXSIZE] = {0};  39     char ch;  40    
 41     Heap H = CreatHeap(); /* 建空堆 */
 42     Tree T = NewTreeNode();  /* 建臨時樹結點 */
 43     
 44     scanf("%d", &N);  /* 樹結點個數 */
 45     for(int i = 0; i < N; i++)  46  {  47         scanf(" %c", &ch);  48         scanf("%d", &Weight[ch]);  49         T->Weight = Weight[ch];  50         H->Data[H->Size].Left = H->Data[H->Size].Right = NULL;  51         Insert(H, *T); /* 複製建立的樹結點(傳參), 插入堆, 造成樹森林 */
 52  }  53     
 54     free(T); /* 釋放臨時結點 */
 55     
 56     T = Huffman(H);   /* 建Huffman樹 */
 57     
 58     int codelen = WPL(T, 0); /* 求Huffman樹的WPL */    
 59     int M;  /* M棵樹 */
 60     scanf("%d", &M);  61     
 62     while(M--)  63     {    /* 一次判斷一棵樹 */
 64         if(Judge(codelen, Weight, N)) printf("Yes\n");  65         else printf("No\n");  66  }  67     
 68     return 0;  69 }  70 
 71  /* 建樹結點 */
 72 Tree NewTreeNode() {  73  Tree T;  74     T = (Tree)malloc(sizeof(struct TreeNode));  75     T->Weight = 0;  76     T->Left = T->Right = NULL;  77     return T;  78 }  79 
 80  /* 建空堆 */
 81 Heap CreatHeap() {  82  Heap H;  83     H = (Heap)malloc(sizeof(struct HeapNode));  84     H->Size = 0;            /* 空堆 */
 85     H->Data[0].Weight = -1; /* 哨兵 */
 86     return H;  87 }  88  
 89  /* 堆插入 */
 90 void Insert(Heap H, struct TreeNode T) {  91     int i = ++H->Size;  /* ++堆, 從堆的最後開始尋找插入結點位置 */
 92     for( ; T.Weight < H->Data[i/2].Weight; i /= 2)  93         H->Data[i] = H->Data[i/2]; /* 父結點下濾 */
 94     H->Data[i] = T; /* 插入結點 */
 95 }  96 
 97  /* 堆刪除 */
 98 Tree Delete(Heap H)  99 {    /* 提取堆最後一個樹結點, 從堆的第一個結點開始比較,上濾, 堆-- */
100     int parent, child; 101     struct TreeNode Temp = H->Data[H->Size--]; /* 提取堆最後一個樹結點 */
102     Tree T = NewTreeNode(); /* 建立樹結點 */
103     *T = H->Data[1];        /* 從堆中提取第一個樹結點 */
104     for(parent = 1; 2*parent <= H->Size; parent = child) 105  { 106         child = 2 * parent; /* 從父結點找左孩子 */
107         if(child != H->Size && H->Data[child].Weight > H->Data[child+1].Weight) 108             child++;        /* 有右孩子且比左孩子小, 選右孩子 */
109         if(Temp.Weight < H->Data[child].Weight) 110             break;  /* 原堆最後一個樹結點找到位置 */
111         H->Data[parent] = H->Data[child]; /* 孩子結點上濾, 孩子結點覆蓋父結點 */
112  } 113     H->Data[parent] = Temp; /* 原堆最後一個樹結點歸位 */
114     return T; /* 返回原堆第一個樹結點 */
115 } 116 
117 /* 建Huffman樹 */
118 Tree Huffman(Heap H) 119 { 120     Tree T = NewTreeNode(); /* 臨時樹結點 */
121     while(H->Size != 1) 122     {    /* 每次取堆中2個最小值建中間樹結點 */
123         T->Left = Delete(H); 124         T->Right = Delete(H); 125         T->Weight = T->Left->Weight + T->Right->Weight; 126         
127         Insert(H, *T); /* 複製建立的中間樹結點(傳參)插入堆 */
128  } 129     free(T); /* 釋放臨時結點 */
130     T = Delete(H); /* 取出堆中的樹 */
131     return T; 132 } 133  
134 /* 帶權路徑長度 */
135 int WPL(Tree T, int Depth) { /* 整棵樹的WPL */
136     if(!T->Left && !T->Right) {  return Depth*T->Weight; } 137     else return WPL(T->Left, Depth+1) + WPL(T->Right, Depth+1); 138 } 139 
140 /* 判斷是否正確的Huffman編碼 */
141 int Judge(int codelen, int Weight[], int N) 142 { 143     int i, j, wgh; /* 權重wgh*/
144     int flag = 1, count = 1; /* 前綴碼, 結點個數 */
145     char ch[2], s[MAXSIZE];     /* 葉結點 編碼*/
146     
147     Tree T = NewTreeNode(), t = NULL; /* 樹根 */
148     
149     /* 建樹*/
150     for(i = 0; i < N; i++)  /* N個葉子 */
151  { 152         t = T; /* 樹根 */
153         scanf("%s%s", ch, s); /* 葉結點 編碼*/
154         
155         wgh = Weight[ch[0]];  /* 葉結點的權重 */    
156                             
157         for(j = 0; s[j]; j++)/* 由根向葉子建一枝樹 */
158  { 159             if(s[j] == '0') { 160                 if(!t->Left){ 161                     t->Left = NewTreeNode(); 162                     count++; 163  } 164                 t = t->Left; 165  } 166             if(s[j] == '1') { 167                 if(!t->Right){ 168                     t->Right = NewTreeNode(); 169                     count++; 170  } 171                 t = t->Right; 172  } 173  } 174         
175         if(t->Left || t->Right){/*不是前綴碼*/
176             flag = 0; 177  } 178         else{ 179             t->Weight = wgh; 180  } 181  } 182     
183     /* 前綴碼, 結點數, 帶權路徑長度 */
184     if(!flag || count != 2*N-1 ||codelen != WPL(T, 0)) 185         return 0; 186     return 1; 187 }
 1 /* 
 2  建一個最小堆, 堆插入樹結點, 造成樹結點森林;  3  每次從堆中取2個最小樹結點, 建中間樹結點並插入堆;  4  最後堆中森林造成一棵Huffman樹並計算WPL;  5  判斷給定的葉結點及編碼, 是否爲正確的編碼;  6 */
 7 
 8 #include <stdio.h>
 9 #include <stdlib.h>
 10 #include <string.h>
 11 
 12 /* 二叉樹結點 */
 13 typedef struct TreeNode* Tree;  14 struct TreeNode {  15     int Weight;  16  Tree Left, Right;  17 };  18 
 19 /* 堆(優先隊列) */
 20 #define MAXSIZE 256 
 21 typedef struct HeapNode* Heap;  22 struct HeapNode {  23     struct TreeNode Data[MAXSIZE];/* 徹底二叉樹順序存儲 */
 24     int Size;  25 };  26  
 27 Tree NewTreeNode();/* 建樹結點 */
 28 Heap CreatHeap(); /* 建空堆 */
 29 void Insert(Heap H, struct TreeNode T);/* 堆插入 */
 30 Tree Delete(Heap H);/* 堆刪除 */
 31 Tree Huffman(Heap H); /* 建Huffman樹 */
 32 int WPL(Tree T, int Depth);/* 整棵樹的WPL */
 33 
 34 int cnt1 = 0, cnt2 = 0;  /* 結點度爲1度爲2的全局變量 */
 35 void JudgeTree(Tree T); /* 判斷樹是否有度爲1的結點 */
 36 int Judge(int codelen, int Weight[], int N) ; /* 判斷是否正確的Huffman編碼 */
 37 
 38 int main()  39 {  40     int N, Weight[MAXSIZE] = {0};  41     char ch;  42    
 43     Heap H = CreatHeap(); /* 建空堆 */
 44     Tree T = NewTreeNode();  /* 建臨時樹結點 */
 45     
 46     scanf("%d", &N);  /* 樹結點個數 */
 47     for(int i = 0; i < N; i++)  48  {  49         scanf(" %c", &ch);  50         scanf("%d", &Weight[ch]);  51         T->Weight = Weight[ch];  52         H->Data[H->Size].Left = H->Data[H->Size].Right = NULL;  53         Insert(H, *T); /* 複製建立的樹結點(傳參), 插入堆, 造成樹森林 */
 54  }  55     
 56     free(T); /* 釋放臨時結點 */
 57     
 58     T = Huffman(H);   /* 建Huffman樹 */
 59     
 60     int codelen = WPL(T, 0); /* 求Huffman樹的WPL */    
 61     int M;  /* M棵樹 */
 62     scanf("%d", &M);  63     
 64     while(M--)  65     {    /* 一次判斷一棵樹 */
 66         if(Judge(codelen, Weight, N)) printf("Yes\n");  67         else printf("No\n");  68  }  69     
 70     return 0;  71 }  72 
 73  /* 建樹結點 */
 74 Tree NewTreeNode() {  75  Tree T;  76     T = (Tree)malloc(sizeof(struct TreeNode));  77     T->Weight = 0;  78     T->Left = T->Right = NULL;  79     return T;  80 }  81 
 82  /* 建空堆 */
 83 Heap CreatHeap() {  84  Heap H;  85     H = (Heap)malloc(sizeof(struct HeapNode));  86     H->Size = 0;            /* 空堆 */
 87     H->Data[0].Weight = -1; /* 哨兵 */
 88     return H;  89 }  90  
 91  /* 堆插入 */
 92 void Insert(Heap H, struct TreeNode T) {  93     int i = ++H->Size;  /* ++堆, 從堆的最後開始尋找插入結點位置 */
 94     for( ; T.Weight < H->Data[i/2].Weight; i /= 2)  95         H->Data[i] = H->Data[i/2]; /* 父結點下濾 */
 96     H->Data[i] = T; /* 插入結點 */
 97 }  98 
 99  /* 堆刪除 */
100 Tree Delete(Heap H) 101 {    /* 提取堆最後一個樹結點, 從堆的第一個結點開始比較,上濾, 堆-- */
102     int parent, child; 103     struct TreeNode Temp = H->Data[H->Size--]; /* 提取堆最後一個樹結點 */
104     Tree T = NewTreeNode(); /* 建立樹結點 */
105     *T = H->Data[1];        /* 從堆中提取第一個樹結點 */
106     for(parent = 1; 2*parent <= H->Size; parent = child) 107  { 108         child = 2 * parent; /* 從父結點找左孩子 */
109         if(child != H->Size && H->Data[child].Weight > H->Data[child+1].Weight) 110             child++;        /* 有右孩子且比左孩子小, 選右孩子 */
111         if(Temp.Weight < H->Data[child].Weight) 112             break;  /* 原堆最後一個樹結點找到位置 */
113         H->Data[parent] = H->Data[child]; /* 孩子結點上濾, 孩子結點覆蓋父結點 */
114  } 115     H->Data[parent] = Temp; /* 原堆最後一個樹結點歸位 */
116     return T; /* 返回原堆第一個樹結點 */
117 } 118 
119 /* 建Huffman樹 */
120 Tree Huffman(Heap H) 121 { 122     Tree T = NewTreeNode(); /* 臨時樹結點 */
123     while(H->Size != 1) 124     {    /* 每次取堆中2個最小值建中間樹結點 */
125         T->Left = Delete(H); 126         T->Right = Delete(H); 127         T->Weight = T->Left->Weight + T->Right->Weight; 128         
129         Insert(H, *T); /* 複製建立的中間樹結點(傳參)插入堆 */
130  } 131     free(T); /* 釋放臨時結點 */
132     T = Delete(H); /* 取出堆中的樹 */
133     return T; 134 } 135  
136 /* 帶權路徑長度 */
137 int WPL(Tree T, int Depth) { /* 整棵樹的WPL */
138     if(!T->Left && !T->Right) {  return Depth*T->Weight; } 139     else return WPL(T->Left, Depth+1) + WPL(T->Right, Depth+1); 140 } 141 
142 /* 判斷樹是否存在度爲1的結點 */
143 void JudgeTree(Tree T) 144 { 145     if(T) { 146         if(T->Left && T->Right) cnt2++; 147         else if(!T->Left && !T->Right) cnt1++; 148         else cnt1 = 0; /* 判斷是否存在度爲1的結點 */
149         JudgeTree(T->Left); 150         JudgeTree(T->Right); 151  } 152 } 153 
154 /* 判斷是否正確的Huffman編碼 */
155 int Judge(int codelen, int Weight[], int N) 156 { 157     int i, j, wgh, flag = 1;  /* 編碼正確標誌flag */
158     char ch[2], s[MAXSIZE]; 159     Tree T = NewTreeNode(), t = NULL; 160     /* 1.建樹(2個狀況) */
161     for(i = 0; i < N; i++)  /* N個葉子 */
162  { 163         t = T; /* 樹根 */
164         scanf("%s%s", ch, s); 165         wgh = Weight[ch[0]]; 166         
167         /* 1.1. 樹高超過告終點數*/        
168         if(strlen(s) > N) { 169             flag = 0; 170             break; 171  } 172         
173         /* 1.2. 由根向葉子建樹 */            
174         for(j = 0; s[j]; j++) 175  { 176             if(s[j] == '0') { 177                 if(!t->Left) t->Left = NewTreeNode(); 178                 t = t->Left; 179  } 180             if(s[j] == '1') { 181                 if(!t->Right) t->Right = NewTreeNode(); 182                 t = t->Right; 183  } 184             
185             if(!s[j+1]) /* 葉結點權重 */
186  { 187                 if(t->Left || t->Right)/*不是前綴碼*/
188  { 189                     flag = 0; 190                     break; 191  } 192                 t->Weight = wgh; 193  } 194  } 195  } 196     
197     /* 1.樹高超過告終點數或不是前綴碼*/
198     if(!flag) 199         return 0; 200     
201     /* 2.判斷是否存在度爲1的結點 */
202     cnt1 = cnt2 = 0; 203  JudgeTree(T); 204     if(cnt1 != cnt2 + 1) 205         return 0; 206     
207     /* 3.帶權路徑長度WPL是否相等*/
208     if(codelen != WPL(T, 0)) 209         return 0; 210     
211     /* 4.編碼正確 */
212     return 1; 213 }
 1 /* 
 2  編碼的字符是雙數個,而提交採用的是等長編碼  3  僅判斷葉結點和度的算法 測試點5不過  4  須要判斷用例與Huffman樹的WPL是否相等  5 */
 6 
 7 #include <stdio.h>
 8 #include <stdlib.h>
 9 #include <string.h>
 10 
 11 #define MAXSIZE 256 
 12 
 13 /* 二叉樹結點 */
 14 typedef struct TreeNode* Tree;  15 struct TreeNode {  16     int Weight;  17  Tree Left, Right;  18 };  19 
 20 Tree NewTreeNode();/* 建樹結點 */
 21 
 22 int cnt1 = 0, cnt2 = 0;  /* 結點度爲1度爲2的全局變量 */
 23 void JudgeTree(Tree T); /* 判斷樹是否有度爲1的結點 */
 24 int Judge(int Weight[], int N) ; /* 判斷是否正確的Huffman編碼 */
 25 
 26 int main()  27 {  28     int N, Weight[MAXSIZE] = {0};  29     char ch;  30        
 31     scanf("%d", &N);  /* 樹結點個數 */
 32     for(int i = 0; i < N; i++)  33  {  34         scanf(" %c", &ch);  35         scanf("%d", &Weight[ch]);  36  }  37     
 38     int M;  /* M棵樹 */
 39     scanf("%d", &M);  40     
 41     while(M--)  42     {    /* 一次判斷一棵樹 */
 43         if(Judge(Weight, N)) printf("Yes\n");  44         else printf("No\n");  45  }  46     
 47     return 0;  48 }  49 
 50  /* 建樹結點 */
 51 Tree NewTreeNode() {  52  Tree T;  53     T = (Tree)malloc(sizeof(struct TreeNode));  54     T->Weight = 0;  55     T->Left = T->Right = NULL;  56     return T;  57 }  58 
 59 /* 判斷樹是否存在度爲1的結點 */
 60 void JudgeTree(Tree T)  61 {  62     if(T) {  63         if(T->Left && T->Right) cnt2++;  64         else if(!T->Left && !T->Right) cnt1++;  65         else cnt1 = 0;  66         JudgeTree(T->Left);  67         JudgeTree(T->Right);  68  }  69 }  70 
 71 int Judge(int Weight[], int N)  72 {  73     int i, j, wgh, flag = 1;  /* 編碼正確標誌flag */
 74     char ch[2], s[MAXSIZE];  75     Tree T = NewTreeNode(), t = NULL;  76     /* 1.建樹(2個狀況) */
 77     for(i = 0; i < N; i++)  /* N個葉子 */
 78  {  79         t = T; /* 樹根 */
 80         scanf("%s%s", ch, s);  81         wgh = Weight[ch[0]];  82         
 83         /* 1.1. 樹高超過告終點數*/        
 84         if(strlen(s) > N) {  85             flag = 0;  86             break; 
 87  }  88         
 89         /* 1.2. 由根向葉子建樹 */            
 90         for(j = 0; s[j]; j++)  91  {  92             if(s[j] == '0') {  93                 if(!t->Left) t->Left = NewTreeNode();  94                 t = t->Left;  95  }  96             if(s[j] == '1') {  97                 if(!t->Right) t->Right = NewTreeNode();  98                 t = t->Right;  99  } 100             
101             if(!s[j+1]) /* 葉結點權重 */
102  { 103                 if(t->Left || t->Right)/*不是前綴碼*/
104  { 105                     flag = 0; 106                     break; 
107  } 108                 t->Weight = wgh; 109  } 110  } 111  } 112     
113     /* 1.樹高超過告終點數或不是前綴碼*/
114     if(!flag) 115         return 0; 116     
117     /* 2.判斷是否存在度爲1的結點 */
118     cnt1 = cnt2 = 0; 119  JudgeTree(T); 120     if(cnt1 != cnt2 + 1) 121         return 0; 122     
123     /* 3.編碼正確 */
124     return 1; 125 }

06-圖1 列出連通集

給定一個有N個頂點和E條邊的無向圖,請用DFS和BFS分別列出其全部的連通集。假設頂點從0到N−1編號。進行搜索時,假設咱們老是從編號最小的頂點出發,按編號遞增的順序訪問鄰接點。

輸入格式:

輸入第1行給出2個整數N(0<N≤10)和E,分別是圖的頂點數和邊數。隨後E行,每行給出一條邊的兩個端點。每行中的數字之間用1空格分隔。

輸出格式:

按照"{ v1v2... vk}"的格式,每行輸出一個連通集。先輸出DFS的結果,再輸出BFS的結果。

輸入樣例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

輸出樣例:

{ 0 1 4 2 7 } { 3 5 } { 6 } { 0 1 2 7 4 } { 3 5 } { 6 }
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <stdbool.h>
 4 
 5 /* 定義圖 */
 6 #define MaxVertex 100        /* 頂點個數 */
 7 typedef int Vertex;          /* 頂點類型定義 */
 8 int G[MaxVertex][MaxVertex]; /* 圖的鄰接矩陣 */
 9 int Nv, Ne;                  /* 圖的頂點及邊 */
 10 bool visit[MaxVertex];       /* 頂點是否訪問數組標記 */
 11 
 12 /* 隊列結構體(順序隊列) */
 13 #define ERROR -1
 14 typedef struct QNode *Queue;  15 struct QNode {  16     Vertex *Data;     /* 存儲元素的數組 */
 17     int Front, Rear;  /* 隊列的頭、尾指針 */
 18     int MAXSIZE;           /* 隊列最大容量 */
 19 };  20 
 21 Queue CreateQueue();  22 bool IsFull( Queue Q );  23 bool AddQ( Queue Q, Vertex X );  24 bool IsEmpty( Queue Q );  25 Vertex DeleteQ( Queue Q );  26 
 27 void BuildGraph();       /* 建圖 */
 28 void DFS(Vertex v); /* DFS */
 29 void BFS(Vertex v); /* BFS */
 30 void PrintConnectedSet(void(*Traverse)(Vertex));  /* 遍歷聯通集 */
 31 
 32 int main()  33 {  34  BuildGraph();  35  PrintConnectedSet(DFS);  36  PrintConnectedSet(BFS);  37     return 0;  38 }  39 
 40 Queue CreateQueue()  41 {  42     Queue Q = (Queue)malloc(sizeof(struct QNode));  43     Q->Data = (Vertex *)malloc(MAXSIZE * sizeof(Vertex));  44     Q->Front = Q->Rear = 0;  45     Q->MAXSIZE = MaxVertex;  46     return Q;  47 }  48  
 49 bool IsFull( Queue Q )  50 {  51     return ((Q->Rear+1)%Q->MAXSIZE == Q->Front);  52 }  53  
 54 bool AddQ( Queue Q, Vertex X )  55 {  56     if ( IsFull(Q) ) {  57         return false;  58  }  59     else {  60         Q->Rear = (Q->Rear+1)%Q->MAXSIZE;  61         Q->Data[Q->Rear] = X;  62         return true;  63  }  64 }  65  
 66 bool IsEmpty( Queue Q )  67 {  68     return (Q->Front == Q->Rear);  69 }  70  
 71 Vertex DeleteQ( Queue Q )  72 {  73     if ( IsEmpty(Q) ) {  74         return ERROR;  75  }  76     else {  77         Q->Front =(Q->Front+1)%Q->MAXSIZE;  78         return  Q->Data[Q->Front];  79  }  80 }  81 
 82 /* 建圖 */
 83 void BuildGraph()  84 {  85     scanf("%d", &Nv);  86     for(int i=0; i<Nv; ++i)  87  {  88         visit[i] = false;  /* 圖的頂點置爲未訪問 */
 89         for(int j=0; j<Nv; j++)  90             G[i][j] = 0;   /* 圖的頂點之間置爲未鏈接 */        
 91  }  92     scanf("%d", &Ne);       /* 輸入圖的邊, 頂點對 */
 93     for(int i=0; i<Ne; i++)  94  {  95  Vertex v1, v2;  96         scanf("%d%d", &v1, &v2);  97         G[v1][v2] = 1;  98         G[v2][v1] = 1;      /* 無向圖 */
 99  } 100 } 101 
102 /* DFS */
103 void DFS(Vertex v) 104 { 105     visit[v] = true; /* 標記已訪問 */
106     printf(" %d", v); 107     for(Vertex i=0; i<Nv; i++) /* 與該頂點鄰接的頂點 */
108         if(!visit[i] && G[v][i]) 109  DFS(i); 110 } 111 
112 /* BFS */
113 void BFS(Vertex v) 114 { 115     Queue q = CreateQueue(); /* 建隊列 */
116     visit[v] = true;         /* 訪問頂點 */
117     printf(" %d", v); 118     AddQ(q,v);               /* 頂點入隊 */
119     while(!IsEmpty(q)) 120  { 121         Vertex t = DeleteQ(q); /* 出隊隊首元素 */ 
122         for(Vertex i=0; i<Nv; ++i) /* 與該頂點鄰接的頂點 */
123  { 124             if(!visit[i] && G[t][i]) /* 未訪問的鄰接頂點 */
125  { 126                 visit[i] = true; /* 訪問頂點 */
127                 printf(" %d", i); 128                 AddQ(q,i);       /* 頂點入隊 */
129  } 130  } 131  } 132 } 133 
134 /* 遍歷聯通集 */
135 void PrintConnectedSet(void(*Traverse)(Vertex)) 136 { 137     for(Vertex i=0; i<Nv; ++i) /*遍歷頂點 */
138  { 139         if(!visit[i]){ 140             printf("{"); 141             Traverse(i); /* DFS, BFS */
142             printf(" }\n"); 143  } 144  } 145     for(Vertex i=0;i<Nv;i++) /* 頂點恢復未訪問 */
146         visit[i] = false; 147 }

06-圖2 Saving James Bond - Easy Version

This time let us consider the situation in the movie "Live and Let Die" in which James Bond, the world's most famous spy, was captured by a group of drug dealers. He was sent to a small piece of land at the center of a lake filled with crocodiles. There he performed the most daring action to escape -- he jumped onto the head of the nearest crocodile! Before the animal realized what was happening, James jumped again onto the next big head... Finally he reached the bank before the last crocodile could bite him (actually the stunt man was caught by the big mouth and barely escaped with his extra thick boot).

Assume that the lake is a 100 by 100 square one. Assume that the center of the lake is at (0,0) and the northeast corner at (50,50). The central island is a disk centered at (0,0) with the diameter of 15. A number of crocodiles are in the lake at various positions. Given the coordinates of each crocodile and the distance that James could jump, you must tell him whether or not he can escape.

Input Specification:

Each input file contains one test case. Each case starts with a line containing two positive integers N (≤100), the number of crocodiles, and D, the maximum distance that James could jump. Then N lines follow, each containing the (x,y) location of a crocodile. Note that no two crocodiles are staying at the same position.

Output Specification:

For each test case, print in a line "Yes" if James can escape, or "No" if not.

Sample Input 1:

14 20
25 -15
-25 28
8 49
29 15
-35 -2
5 28
27 -29
-8 -28
-20 -35
-25 -20
-13 29
-30 15
-35 40
12 12

Sample Output 1:

Yes

Sample Input 2:

4 13
-12 12
12 12
-12 -12
12 -12

Sample Output 2:

No
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <math.h>
 4 #include <stdbool.h>
 5 
 6 /* 鱷魚結點 */
 7 #define MaxVertexNum 101
 8 struct Node{  9     int x;    /* 橫座標 */
10     int y;    /* 縱座標 */
11     bool visit;       /* 是否被訪問 */
12     bool toshore;     /* 是否能上岸 */
13 }; 14 
15 int N;    /* 鱷魚數 */ 
16 int D;    /* 跳躍距離 */
17 struct Node G[MaxVertexNum]; /* 鱷魚圖 */
18 bool Escape = false; /* 逃離 */
19 
20 void Init();/* 圖初始化 */ 
21 bool Shore(int x, int y, double d); /* 可否到岸 */
22 bool Jump(int x1, int y1, int x2, int y2, double d); /* 可否跳上去 */
23 void DFS(int v);  /* 深搜 */
24 void listCompoent();/* 遍歷全部第一步能跳到的鱷魚 */
25 
26 int main() 27 { 28  Init(); 29  listCompoent(); 30     return 0; 31 } 32 
33 void Init() 34 { 35     scanf("%d%d", &N, &D); 36     int x,y; 37     for(int i=0;i<N;i++) 38  { 39         scanf("%d%d", &x, &y); 40         G[i].x = x; 41         G[i].y = y; 42         G[i].visit = false; 43         G[i].toshore = false; 44         if(Shore(x,y,D)) G[i].toshore = true; 45  } 46 } 47 
48 bool Shore(int x, int y, double d){ 49     return abs(x-50)<=d || abs(x+50)<=d || abs(y+50)<=d || abs(y-50) <= d; 50 } 51 
52 bool Jump(int x1, int y1, int x2, int y2, double d){ 53     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) <= d; 54 } 55 
56 void DFS(int v) 57 { 58     if(G[v].toshore){ 59         Escape = true; 60         return; 61  } 62     G[v].visit = true; 63     for(int i=0; i<N; i++){  /* 沒被訪問且能夠跳上去的鱷魚v to i */
64         if(!G[i].visit && Jump(G[v].x, G[v].y, G[i].x, G[i].y, D)) 65  DFS(i); 66  } 67 } 68 
69 void listCompoent() 70 { 71     for(int i=0; i<N; i++) 72  { 73         if(Jump(G[i].x, G[i].y, 0, 0, D+15/2)) /* first jump */
74  { 75  DFS(i); 76  } 77  } 78     if(Escape) 79         printf("Yes\n"); 80     else
81         printf("No\n"); 82 }

06-圖3 六度空間

「六度空間」理論又稱做「六度分隔(Six Degrees of Separation)」理論。這個理論能夠通俗地闡述爲:「你和任何一個陌生人之間所間隔的人不會超過六個,也就是說,最多經過五我的你就可以認識任何一個陌生人。」如圖所示。

 

「六度空間」理論雖然獲得普遍的認同,而且正在獲得愈來愈多的應用。可是數十年來,試圖驗證這個理論始終是許多社會學家努力追求的目標。然而因爲歷史的緣由,這樣的研究具備太大的侷限性和困難。隨着當代人的聯絡主要依賴於電話、短信、微信以及因特網上即時通訊等工具,可以體現社交網絡關係的一手數據已經逐漸使得「六度空間」理論的驗證成爲可能。

 假如給你一個社交網絡圖,請你對每一個節點計算符合「六度空間」理論的結點佔結點總數的百分比。

輸入格式:

輸入第1行給出兩個正整數,分別表示社交網絡圖的結點數N(1<N≤103,表示人數)、邊數M(≤33×N,表示社交關係數)。隨後的M行對應M條邊,每行給出一對正整數,分別是該條邊直接連通的兩個結點的編號(節點從1到N編號)。

輸出格式:

對每一個結點輸出與該結點距離不超過6的結點數佔結點總數的百分比,精確到小數點後2位。每一個結節點輸出一行,格式爲「結點編號:(空格)百分比%」。

輸入樣例:

10 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10

輸出樣例:

1: 70.00%
2: 80.00%
3: 90.00%
4: 100.00%
5: 100.00%
6: 100.00%
7: 100.00%
8: 90.00%
9: 80.00%
10: 70.00%
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <stdbool.h>
 4 
 5 /* 鄰接表結點 */
 6 #define MaxVertex 10005
 7 typedef int Vertex;  8 typedef struct Node *AdjList;  9 struct Node{  10     Vertex Adjv;   /* 頂點 */
 11  AdjList Next;  12 };  13 
 14 AdjList G[MaxVertex];    /* 鄰接表數組 */
 15 bool visit[MaxVertex];   /* 是否訪問 */ 
 16 int N;   /* 結點數 */
 17 int M;   /* 邊數 */
 18 
 19 /* 隊列結構體(順序隊列) */
 20 #define ERROR -1
 21 typedef struct QNode *Queue;  22 struct QNode {  23     Vertex *Data;     /* 存儲元素的數組 */
 24     int Front, Rear;  /* 隊列的頭、尾指針 */
 25     int MAXSIZE;           /* 隊列最大容量 */
 26 };  27 
 28 Queue CreateQueue();  29 bool IsFull( Queue Q );  30 bool AddQ( Queue Q, Vertex X );  31 bool IsEmpty( Queue Q );  32 Vertex DeleteQ( Queue Q );  33 
 34 void InitVisit(); /* 訪問狀態初始值 */
 35 void Init(); /* 初始化 */
 36 int BFS(Vertex v);  37 void output(double result,int i);  38 void SDS();  39 
 40 int main()  41 {  42  Init();  43  SDS();  44     return 0;  45 }  46 
 47 Queue CreateQueue()  48 {  49     Queue Q = (Queue)malloc(sizeof(struct QNode));  50     Q->Data = (Vertex *)malloc(MaxVertex * sizeof(Vertex));  51     Q->Front = Q->Rear = 0;  52     Q->MAXSIZE = MaxVertex;  53     return Q;  54 }  55  
 56 bool IsFull( Queue Q )  57 {  58     return ((Q->Rear+1)%Q->MAXSIZE == Q->Front);  59 }  60  
 61 bool AddQ( Queue Q, Vertex X )  62 {  63     if ( IsFull(Q) ) {  64         return false;  65  }  66     else {  67         Q->Rear = (Q->Rear+1)%Q->MAXSIZE;  68         Q->Data[Q->Rear] = X;  69         return true;  70  }  71 }  72  
 73 bool IsEmpty( Queue Q )  74 {  75     return (Q->Front == Q->Rear);  76 }  77  
 78 Vertex DeleteQ( Queue Q )  79 {  80     if ( IsEmpty(Q) ) {  81         return ERROR;  82  }  83     else {  84         Q->Front =(Q->Front+1)%Q->MAXSIZE;  85         return  Q->Data[Q->Front];  86  }  87 }  88 
 89 void InitVisit(){ /* 訪問狀態初始值 */
 90     for(int i=1; i<=N; ++i)  91         visit[i] = false;  92 }  93 
 94 void Init() /* 初始化 */
 95 {  96  Vertex v1,v2;  97  AdjList NewNode;  98     scanf("%d%d", &N, &M);  99     
100     for(int i=1; i<=N; ++i){  /* 鄰接表初始化 1—N */
101         G[i] = (AdjList)malloc(sizeof(struct Node)); 102         G[i]->Adjv = i;     /* 鄰接表下標 */
103         G[i]->Next = NULL;  /* 鄰接表指針 */
104  } 105 
106     for(int i=0; i<M; ++i){  /* 邊初始值 */
107         scanf("%d%d", &v1, &v2); 108         
109         NewNode = (AdjList)malloc(sizeof(struct Node)); 110         NewNode->Adjv = v2;         /* 新結點 */
111         
112         NewNode->Next = G[v1]->Next; /* 連接 */
113         G[v1]->Next = NewNode; 114         
115         NewNode = (AdjList)malloc(sizeof(struct Node)); 116         NewNode->Adjv = v1;          /* 新結點 */
117         
118         NewNode->Next = G[v2]->Next; /* 連接 */
119         G[v2]->Next = NewNode; 120  } 121 } 122 
123 int BFS(Vertex v) 124 { 125     Queue q = CreateQueue(); 126  Vertex t; 127     int level = 0; 128     int last = v;     /* 該層最後一次訪問的結點 */ 
129     int tail = v;     /* 每次在變的結點 */ 
130     AdjList node;     /* 鄰接表結點 */
131     visit[v] = true; 132     int count = 1;    /* 統計關係數 */ 
133     AddQ(q,v);        /* 頂點入隊 */
134     while(!IsEmpty(q)) 135  { 136         t = DeleteQ(q);   /* 頂點出隊 */
137 
138         node = G[t]->Next; /* G[i]第一個結點存本身的下標 */
139         while(node) 140  { 141             if(!visit[node->Adjv]){ 142                 visit[node->Adjv] = true; 143                 AddQ(q, node->Adjv); 144                 count++; 145                 tail = node->Adjv; /* 每次更新該結點 */
146  } 147             node = node->Next; 148  } 149     
150         if(t == last){  /* 若是該當前結點是這層最後一個結點 */
151             level++;      /* 層數 +1 */  
152             last = tail;  /* 更改 last */
153  } 154         
155         if(level==6)  /* 6層結束 */
156            break; 157  } 158     return count; 159 } 160 
161 
162 void output(double result, int i){ 163     printf("%d: %.2f%%\n", i, result); 164 } 165 
166 void SDS()  /* 六度空間搜索 six degree search */
167 { 168     int count; 169     for(int i=1; i<=N; i++){ 170         InitVisit();     /* 每次初始化訪問數組 */
171         count = BFS(i);   /* 搜索結果, 結點數count */
172         output((100.0*count)/N, i); 173  } 174 }

07-圖4 哈利·波特的考試

哈利·波特要考試了,他須要你的幫助。這門課學的是用魔咒將一種動物變成另外一種動物的本事。例如將貓變成老鼠的魔咒是haha,將老鼠變成魚的魔咒是hehe等等。反方向變化的魔咒就是簡單地將原來的魔咒倒過來念,例如ahah能夠將老鼠變成貓。另外,若是想把貓變成魚,能夠經過念一個直接魔咒lalala,也能夠將貓變老鼠、老鼠變魚的魔咒連起來念:hahahehe。

如今哈利·波特的手裏有一本教材,裏面列出了全部的變形魔咒和能變的動物。老師容許他本身帶一隻動物去考場,要考察他把這隻動物變成任意一隻指定動物的本事。因而他來問你:帶什麼動物去可讓最難變的那種動物(即該動物變爲哈利·波特本身帶去的動物所須要的魔咒最長)須要的魔咒最短?例如:若是隻有貓、鼠、魚,則顯然哈利·波特應該帶鼠去,由於鼠變成另外兩種動物都只須要念4個字符;而若是帶貓去,則至少須要念6個字符才能把貓變成魚;同理,帶魚去也不是最好的選擇。

輸入格式:

輸入說明:輸入第1行給出兩個正整數N (≤100)和M,其中N是考試涉及的動物總數,M是用於直接變形的魔咒條數。爲簡單起見,咱們將動物按1~N編號。隨後M行,每行給出了3個正整數,分別是兩種動物的編號、以及它們之間變形須要的魔咒的長度(≤100),數字之間用空格分隔。

輸出格式:

輸出哈利·波特應該帶去考場的動物的編號、以及最長的變形魔咒的長度,中間以空格分隔。若是隻帶1只動物是不可能完成全部變形要求的,則輸出0。若是有若干只動物均可以備選,則輸出編號最小的那隻。

輸入樣例:

6 11
3 4 70
1 2 1
5 4 50
2 6 50
5 6 60
1 3 70
4 6 60
3 6 80
5 1 100
2 4 60
5 2 80

輸出樣例:

4 70
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 #define MaxVertexNum 100 /* 最大頂點數設爲100 */ 
 5 #define INFINITY 65535   /* ∞設爲雙字節無符號整數的最大值65535*/ 
 6 typedef int Vertex;      /* 用頂點下標表示頂點,爲整型*/ 
 7 typedef int WeightType;  /* 邊的權值設爲整型*/ 
 8 
 9 /* 邊的定義*/ 
 10 typedef struct ENode* PtrToENode;  11 struct ENode{  12     Vertex V1, V2;      /* 有向邊<V1, V2> */ 
 13     WeightType Weight;  /* 權重*/ 
 14 };  15 typedef PtrToENode Edge; /* 邊類型 邊結構體指針 */
 16 
 17 /* 圖結點的定義*/ 
 18 typedef struct GNode* PtrToGNode;  19 struct GNode{  20     int Nv;  /* 頂點數*/ 
 21     int Ne;  /* 邊數*/ 
 22     WeightType G[MaxVertexNum][MaxVertexNum]; /* 鄰接矩陣*/     
 23 };  24 typedef PtrToGNode MGraph; /* 以鄰接矩陣存儲的圖類型 圖結構體指針*/
 25 
 26 MGraph CreateGraph( int VertexNum);/* 初始化一個有VertexNum個頂點但沒有邊的圖*/  
 27 void InsertEdge( MGraph Graph, Edge E );/* 插入邊<V1, V2> */  
 28 MGraph BuildGraph();  /* 1 */
 29 
 30 void Floyd( MGraph Graph, WeightType D[][MaxVertexNum] ); /* 弗洛伊德算法 */
 31 WeightType FindMaxDist( WeightType D[][MaxVertexNum], Vertex i, int N );  32 void FindAnimal( MGraph Graph ); /* 2 */
 33 
 34 int main()  35 {  36     MGraph G = BuildGraph();  37  FindAnimal( G );  38     return 0;  39 }  40 
 41 MGraph CreateGraph( int VertexNum)  42 { /* 初始化一個有VertexNum個頂點但沒有邊的圖*/ 
 43     Vertex V, W;    /* 頂點V W */
 44     MGraph Graph;   /* 圖指針 */
 45     Graph = (MGraph)malloc(sizeof(struct GNode)); /* 創建圖*/ 
 46     Graph->Nv = VertexNum;  /* 圖頂點數 */
 47     Graph->Ne = 0;          /* 沒有邊 */   
 48     /* 初始化鄰接矩陣*/ 
 49     /* 注意:這裏默認頂點編號從0開始,到(Graph->Nv-1) */ 
 50     for(V=0; V<Graph->Nv; V++)  51         for(W=0; W<Graph->Nv; W++)  52             Graph->G[V][W] = INFINITY;  /* 頂點之間沒有邊 */
 53     return Graph;  54 }  55 
 56 void InsertEdge( MGraph Graph, Edge E ) /* 插入邊<V1, V2> */  
 57 {     /* 如果無向圖,還要插入邊<V2, V1> */ 
 58     Graph->G[E->V1][E->V2] = E->Weight;  59     Graph->G[E->V2][E->V1] = E->Weight;  60 }  61 
 62 MGraph BuildGraph()  63 {  64  MGraph Graph;  65  Edge E;  66     int Nv, i;  67     scanf("%d", &Nv);            /* 讀入頂點個數*/ 
 68     Graph = CreateGraph(Nv);     /* 初始化有Nv個頂點但沒有邊的圖*/
 69     scanf("%d", &(Graph->Ne));   /* 讀入邊數*/ 
 70     if( Graph->Ne != 0 ) {       /* 若是有邊*/ 
 71         E = (Edge)malloc(sizeof(struct ENode)); /* 創建邊結點*/ 
 72         /* 讀入邊,格式爲"起點終點權重",插入鄰接矩陣*/ 
 73         for(i=0; i<Graph->Ne; i++) {  74             scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);  75             E->V1--; E->V2--;  /* 起始編號從0開始 */
 76  InsertEdge( Graph, E );  77  }  78  }  79     return Graph;  80 }  81 
 82 void Floyd( MGraph Graph, WeightType D[][MaxVertexNum] )  83 {  84  Vertex i, j, k;  85     /* 初始化*/ 
 86     for( i=0; i<Graph->Nv; i++ )  87         for( j=0; j<Graph->Nv; j++ ) {  88             D[i][j] = Graph->G[i][j];  89  }  90     for( k=0; k<Graph->Nv; k++ )  91         for( i=0; i<Graph->Nv; i++ )  92             for( j=0; j<Graph->Nv; j++ )  93                 if( D[i][k] + D[k][j] < D[i][j] ) {  94                     D[i][j] = D[i][k] + D[k][j];  95  }  96 }  97 
 98 void FindAnimal( MGraph Graph )  99 { 100  WeightType D[MaxVertexNum][MaxVertexNum], MaxDist, MinDist; 101  Vertex Animal, i; 102     
103     Floyd( Graph, D ); /* 多源最短路徑 */
104     
105     MinDist= INFINITY; 106     for( i=0; i<Graph->Nv; i++ ) { 107         MaxDist= FindMaxDist( D, i, Graph->Nv);  /* 第i行的最大值 */
108         if( MaxDist== INFINITY ) { /* 說明有從i沒法變出的動物*/ 
109             printf("0\n"); 110             return; 111  } 112         if( MinDist > MaxDist) { /* 找到最長距離更小的動物*/ 
113             MinDist = MaxDist; 114             Animal = i+1; /* 更新距離,記錄編號*/ 
115  } 116  } 117     printf("%d %d\n", Animal, MinDist); 118 } 119 
120 WeightType FindMaxDist( WeightType D[][MaxVertexNum], Vertex i, int N ) 121 { 122  WeightType MaxDist; 123  Vertex j; 124     MaxDist= 0; 125     for( j=0; j<N; j++ ) /* 找出i到其餘動物j的最長距離*/ 
126         if( i!=j && D[i][j]>MaxDist) /* i==j 對角元的值INFINITY */
127             MaxDist = D[i][j];   /* 第i行的最大值 */
128     return MaxDist; 129 }

下一題預留空格

相關文章
相關標籤/搜索