PTA(浙大数据结构,c语言)

01-复杂度1 最大子列和问题

给定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。现要求你编写程序,计算给定整数序列的最大子列和。

本题旨在测试各种不同的算法在各种数据情况下的表现。各组测试数据特点如下:

数据1:与样例等价,测试基本正确性;

数据2:102个随机整数;

数据3:103个随机整数;

数据4:104个随机整数;

数据5:105个随机整数;

输入格式:

输入第1行给出正整数K (≤);第2行给出K个整数,其间以空格分隔。

输出格式:

在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出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 }

07-图5 Saving James Bond - Hard 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 a shortest path to reach one of the banks. The length of a path is the number of jumps that James has to make.

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, if James can escape, output in one line the minimum number of jumps he must make. Then starting from the next line, output the position (x,y) of each crocodile on the path, each pair in one line, from the island to the bank. If it is impossible for James to escape that way, simply give him 0 as the number of jumps. If there are many shortest paths, just output the one with the minimum first jump, which is guaranteed to be unique.

Sample Input 1:

17 15
10 -21
10 21
-40 10
30 -50
20 40
35 10
0 -10
-25 22
40 -40
-30 30
-10 22
0 11
25 21
25 10
10 10
10 35
-30 10

Sample Output 1:

4
0 11
10 21
10 35

Sample Input 2:

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

Sample Output 2:

0

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <math.h>
  4 
  5 /* 队列定义开始 */
  6 #define MaxSize 101
  7 int Queue[MaxSize];
  8 int front = 0, rear = 0;
  9 /* 队列定义结束 */
 10 
 11 #define MaxVertexNum 100
 12 #define INF 65535
 13 #define ISLAND_DIAMETER 15/2.0
 14 
 15 typedef struct Position Point;
 16 struct Position {
 17     int x;
 18     int y;
 19 };
 20 
 21 Point points[MaxVertexNum]; /* 鳄鱼坐标 */
 22 int dist[MaxVertexNum];     /* 路径长度 */
 23 int path[MaxVertexNum];     /* 下一个结点 */
 24 
 25 void ReadPoints(int num); /* 读取鳄鱼坐标 */
 26 
 27 int Distance(Point p1, Point p2);    /* 求两点间距离 */
 28 int Jump(Point p1, Point p2, int dis);  /* 判断能否跳跃过去 */
 29 int isSafe(Point p, int dis);    /* 是否能跳上岸 */
 30 void PrintPath(int ans);
 31 void Save007(int num, int dis);  /* BFS函数 */
 32 
 33 int main()
 34 {
 35     int num, dis; /* num鳄鱼数 dis James可以跳的最远距离 */
 36     scanf("%d %d", &num, &dis);
 37 
 38     ReadPoints(num);   /* 读取鳄鱼坐标 */
 39     Save007(num, dis); /* 计算并输出 */
 40 
 41     return 0;
 42 }
 43 
 44 void ReadPoints(int num)
 45 {
 46     int i;
 47     for (i = 0; i < num; ++i) {
 48         scanf("%d %d", &(points[i].x), &(points[i].y));
 49     }
 50 }
 51 
 52 int Distance(Point p1, Point p2)
 53 {
 54     return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
 55 }
 56 
 57 int Jump(Point p1, Point p2, int dis)
 58 {
 59     return Distance(p1, p2) <= dis * dis;
 60 }
 61 
 62 int isSafe(Point p, int dis)
 63 {
 64     return ((abs(p.x) + dis) >= 50 || (abs(p.y) + dis) >= 50);
 65 }
 66 
 67 void PrintPath(int ans)
 68 {
 69     printf("%d\n", dist[ans] + 1);
 70     for (; ans != -1; ans = path[ans]) {
 71         printf("%d %d\n", points[ans].x, points[ans].y);
 72     }
 73 }
 74 
 75 void Save007(int num, int dis)
 76 {
 77     int i, cur_dis, pIndex, ans;
 78     Point center;  /* 岛的中心位置 */
 79     center.x = 0; center.y = 0;
 80 
 81     /* 如果从岛上就能直接跳上岸 */
 82     if (isSafe(center, dis + ISLAND_DIAMETER)) {
 83         printf("1\n");
 84         return;
 85     }
 86 
 87     for (i = 0; i < num; ++i) { /* 初始化辅助数组 */
 88         dist[i] = INF;
 89         path[i] = -1;
 90     }
 91     
 92     for (i = 0; i < num; ++i) {
 93         if (isSafe(points[i], dis)) {/* 将所有能上岸的入队 */
 94             dist[i] = 1;
 95             Queue[rear] = i;  /* 入队 */
 96             rear = (rear+1) % MaxSize;
 97         }
 98     }
 99     
100     cur_dis = 1; ans = -1;
101     while (front != rear) 
102     {
103         pIndex = Queue[front];    /* 出队 */
104         front = (front+1) % MaxSize;
105         
106         if (dist[pIndex] == cur_dis + 1 && ans != -1) break;  /* 已经遍历完当前层 */
107         if (Jump(center, points[pIndex], dis + ISLAND_DIAMETER)) {
108             if (ans == -1 || Distance(center, points[pIndex]) < Distance(center, points[ans]))
109                 ans = pIndex;
110         }
111         else {
112             for (i = 0; i < num; ++i) {
113                 if (Jump(points[pIndex], points[i], dis) && (dist[pIndex] + 1 < dist[i])) {
114                     dist[i] = dist[pIndex] + 1;
115                     path[i] = pIndex;
116                     Queue[rear] = i;  /* 入队 */
117                     rear = (rear+1) % MaxSize;
118                 }
119             }
120         }
121         cur_dis = dist[pIndex];
122     }
123     if (ans == -1) printf("0\n");
124     else PrintPath(ans);
125 }

07-图6 旅游规划

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入格式:

输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。

输出格式:

在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

输入样例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

输出样例:

3 40
  1 #include <stdio.h>
  2 #include <stdbool.h>
  3 
  4 #define INF 65535
  5 #define MaxVertexNum 501
  6 
  7 struct node{
  8     int E; /* 距离 */
  9     int C; /* 花费 */
 10 };
 11 
 12 typedef struct node Vertex;     /* 顶点 */
 13 Vertex G[MaxVertexNum][MaxVertexNum];   /* 图 */
 14 
 15 bool collected[MaxVertexNum];   /* 收录 */
 16 int dist[MaxVertexNum];         /* 最近距离 */
 17 int cost[MaxVertexNum];         /* 最少花费 */
 18 
 19 int N;  /* 城市的编号为0~(N−1),顶点数 */
 20 int M;    /* 高速公路的条数 */
 21 int S;    /* 出发地的城市编号 */
 22 int D;  /* 目的地的城市编号 */
 23 
 24 /* 初始化  */
 25 void Init()
 26 {                
 27     scanf("%d%d%d%d", &N, &M, &S, &D);
 28         
 29     for(int i=0; i<N; i++)  /* N个城市 */
 30     { 
 31         for(int j=0; j<N; j++){/* 初始化图 */
 32             G[i][j].E = INF;    
 33             G[i][j].C = INF; 
 34             if(i==j){         /* 对角线距离花费 */
 35                 G[i][j].E = 0; 
 36                 G[i][j].C = 0; 
 37             } 
 38         }
 39         dist[i] = INF;        /* 初始化最近距离 INF*/
 40         cost[i] = 0;          /* 初始化最少花费 0 */
 41         collected[i] = false; /* 初始化收录集合 */
 42     }     
 43     
 44     int v1, v2;
 45     for(int i=0; i<M; i++){ /* M条路*/        
 46         scanf("%d%d", &v1, &v2);  /* 城市1、城市2 */
 47         /* 高速公路长度、收费额 */    
 48         scanf("%d%d", &G[v1][v2].E, &G[v1][v2].C);
 49         G[v2][v1].E = G[v1][v2].E;   /* 无向图 */
 50         G[v2][v1].C = G[v1][v2].C;
 51     }
 52 }
 53 
 54 /* 查找未收录dist最小的点 */
 55 int FindMin( )
 56 {
 57     int min = INF;
 58     int v = -1;
 59     for(int i=0; i<N; i++)
 60         if(!collected[i] && dist[i] < min)
 61         {
 62             min = dist[i];
 63             v = i;
 64         }
 65     return v;
 66 } 
 67 
 68 void Dijkstra( )
 69 { 
 70     dist[S] = 0; /* 起点本身的距离 */
 71     collected[S] = true;
 72     /* 起点的所有邻近城市最少距离和花费 */
 73     for (int V=0; V<N; V++ ) { 
 74         if(G[S][V].E){
 75             dist[V] = G[S][V].E;
 76             cost[V] = G[S][V].C;
 77         }     
 78     }
 79     /* 先将起点收入集合 */  
 80     while (1) 
 81     {
 82         int V = FindMin(  ); /* 查找未收录dist最小的点 */
 83         if ( -1 == V) break;            
 84         collected[V] = true;  /* 收录 */
 85         
 86         for(int W=0; W<N; W++)
 87         {
 88             if ( collected[W] == false )
 89             {    
 90                 if ( dist[V]+G[V][W].E < dist[W] ) {
 91                     dist[W] = dist[V] + G[V][W].E ;                
 92                     cost[W] = cost[V] + G[V][W].C ;
 93                 }
 94                 /* 如果有若干条路径都是最短的 */
 95                 /* 那么需要输出最便宜的一条路径 */
 96                 else if ( (dist[V]+G[V][W].E == dist[W])
 97                     && (cost[V]+G[V][W].C < cost[W]) ){
 98                         cost[W] = cost[V] + G[V][W].C ;
 99                 }
100             }            
101         }        
102     }
103 }
104 
105 int main()
106 {
107     Init();
108     Dijkstra();
109     printf("%d %d", dist[D],cost[D]);
110     return 0;
111 } 

08-图7 公路村村通

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:

输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。

输出格式:

输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。

输入样例:

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

输出样例:

12
 1 #include <stdio.h>
 2 
 3 #define inf 65535
 4 #define MAXN 1005
 5 int map[MAXN][MAXN],distance[MAXN];
 6 int N, M, count = 0, sum = 0;
 7 
 8 void init() 
 9 {
10     for(int i = 1; i<=N; i++) {
11         for(int j = 1; j<=N; j++) {
12             map[i][j] = inf;
13         }
14     }
15     int start,end,cost;
16     for(int i = 0; i<M; i++) 
17     { 
18         scanf("%d%d%d",&start,&end,&cost);      
19         map[start][end] = map[end][start] = cost;      
20     }
21 }
22 
23 void prim() 
24 {    /* 从1顶点出开始生成最小生成树 */
25     for(int i = 2; i<=N; i++){
26         distance[i] = map[1][i]; /* 顶点1到其他顶点的距离 */
27     }
28     distance[1] = -1; /* 代替顶点1,visited */
29     int v = 1,MIN = inf;
30     for(int i = 1; i<N; i++) 
31     {
32         MIN = inf,v = 1;
33         for(int j = 1; j<=N; j++) 
34         {/* 从没有访问过的顶点中找到下一个距离最短的边 */
35             if(distance[j]>0 && distance[j]<MIN) {
36                 MIN = distance[j];
37                 v = j;
38             }
39         }
40         if(MIN != inf)
41         {
42             sum += distance[v];
43             distance[v] = -1; /* 代替visited */
44             for(int j = 1; j<=N; j++) 
45             {  /* 用这个最小的顶点的邻接边的权值更新distance[]的值 */
46                 if(map[v][j]<distance[j]) {
47                     distance[j] = map[v][j];
48                     count++;                    
49                 }
50             }
51         }   
52     }
53     
54     if(count<N){    
55         sum = -1;
56     }
57     printf("%d\n",sum);        
58 }
59 
60 int main() 
61 {
62     scanf("%d%d",&N,&M);
63     init();
64     prim();
65     return 0;
66 }

08-图8 How Long Does It Take

Given the relations of all the activities of a project, you are supposed to find the earliest completion time of the project.

Input Specification:

Each input file contains one test case. Each case starts with a line containing two positive integers N (≤100), the number of activity check points (hence it is assumed that the check points are numbered from 0 to N−1), and M, the number of activities. Then M lines follow, each gives the description of an activity. For the i-th activity, three non-negative numbers are given: S[i], E[i], and L[i], where S[i] is the index of the starting check point, E[i] of the ending check point, and L[i] the lasting time of the activity. The numbers in a line are separated by a space.

Output Specification:

For each test case, if the scheduling is possible, print in a line its earliest completion time; or simply output "Impossible".

Sample Input 1:

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

Sample Output 1:

18

Sample Input 1:

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

Sample Output 1:

Impossible
 1 #include <stdio.h>
 2 
 3 #define MaxVertex 105
 4 #define INF -100000
 5 typedef int Vertex;
 6 
 7 int N;  /* 点 */
 8 int M;  /* 边 */
 9 int G[MaxVertex][MaxVertex];  
10 int Earliest[MaxVertex];  /* 时间  */
11 int Indegree[MaxVertex];  /* 入度  */
12 
13 /* 初始化图  */
14 void build()
15 {
16     Vertex v1,v2,w;
17     scanf("%d%d", &N, &M);
18     for(Vertex i=0; i<N; i++){
19         for(Vertex j=0; j<N; j++)
20             G[i][j] = INF;
21     }
22     for(int i=0;i<M;i++){
23         scanf("%d%d%d", &v1,&v2,&w);
24         G[v1][v2] = w;   /* 有向图  */
25         Indegree[v2]++;  /* v2入度+1  */
26     }
27 }
28 
29 void TopSort()
30 {
31     int cnt = 0;
32     
33     int queue[MaxVertex]; /* 队列 */
34     int front = 0, rear = 0;
35     
36     for(Vertex i=0;i<N;i++)/* 入度为0顶点入队  */
37         if(!Indegree[i]){ 
38             queue[rear] = i;
39             rear = (rear+1) % MaxVertex;
40             Earliest[i] = 0;
41         } 
42     while(front != rear)
43     {
44         Vertex v = queue[front];
45         front = (front+1) % MaxVertex;
46         cnt++;
47         for(Vertex w=0;w<N;w++)
48         {
49             if(G[v][w]!=INF) /* 邻接边 */
50             { 
51                 if(Earliest[w] < Earliest[v]+G[v][w])
52                 {/* 如果周围有时间更长,更新时间  */
53                     Earliest[w] = Earliest[v]+G[v][w];
54                 }                    
55                 if(--Indegree[w]==0)
56                 {
57                     queue[rear] = w;
58                     rear = (rear+1) % MaxVertex;
59                 }                    
60             } 
61         }            
62     }
63     if(cnt!=N)
64         printf("Impossible");
65     else{ /* 也许不止一个终点  */        
66         int max = 0;
67         for(Vertex i=0;i<N;i++)  
68             if(max < Earliest[i]) 
69                 max = Earliest[i];
70         printf("%d", max);
71     }        
72 }
73 
74 int main()
75 {
76     build();
77     TopSort();
78     return 0;
79 }

08-图9 关键活动

假定一个工程项目由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其它一些子任务后才能执行。“任务调度”包括一组子任务、以及每个子任务可以执行所依赖的子任务集。

比如完成一个专业的所有课程学习和毕业设计可以看成一个本科生要完成的一项工程,各门课程可以看成是子任务。有些课程可以同时开设,比如英语和C程序设计,它们没有必须先修哪门的约束;有些课程则不可以同时开设,因为它们有先后的依赖关系,比如C程序设计和数据结构两门课,必须先学习前者。

但是需要注意的是,对一组子任务,并不是任意的任务调度都是一个可行的方案。比如方案中存在“子任务A依赖于子任务B,子任务B依赖于子任务C,子任务C又依赖于子任务A”,那么这三个任务哪个都不能先执行,这就是一个不可行的方案。

任务调度问题中,如果还给出了完成每个子任务需要的时间,则我们可以算出完成整个工程需要的最短时间。在这些子任务中,有些任务即使推迟几天完成,也不会影响全局的工期;但是有些任务必须准时完成,否则整个项目的工期就要因此延误,这种任务就叫“关键活动”。

请编写程序判定一个给定的工程项目的任务调度是否可行;如果该调度方案可行,则计算完成整个工程项目需要的最短时间,并输出所有的关键活动。

输入格式:

输入第1行给出两个正整数N(≤100)和M,其中N是任务交接点(即衔接相互依赖的两个子任务的节点,例如:若任务2要在任务1完成后才开始,则两任务之间必有一个交接点)的数量。交接点按1~N编号,M是子任务的数量,依次编号为1~M。随后M行,每行给出了3个正整数,分别是该任务开始和完成涉及的交接点编号以及该任务所需的时间,整数间用空格分隔。

输出格式:

如果任务调度不可行,则输出0;否则第1行输出完成整个工程项目需要的时间,第2行开始输出所有关键活动,每个关键活动占一行,按格式“V->W”输出,其中V和W为该任务开始和完成涉及的交接点编号。关键活动输出的顺序规则是:任务开始的交接点编号小者优先,起点编号相同时,与输入时任务的顺序相反。

输入样例:

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

输出样例:

17
1->2
2->4
4->6
6->7
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 #define maxn 110 
  6 #define INF 65535
  7 
  8 int map[maxn][maxn];
  9 int indegree[maxn],outdegree[maxn];
 10 int earliest[maxn],latest[maxn];
 11 
 12 void init(int n)
 13 {
 14     for(int i = 1; i <= n; i++){
 15         for(int j = 1; j <= n; j++){
 16             map[i][j] = -1;
 17         }
 18         indegree[i] = 0;
 19         outdegree[i] = 0;
 20         earliest[i] = 0;
 21         latest[i] = INF;
 22     }
 23 }
 24 
 25 int max(int a,int b){
 26     return a > b ? a : b;
 27 }
 28 
 29 int min(int a,int b){
 30     return a < b ? a : b;
 31 }
 32 
 33 int early_time(int n)
 34 {
 35     int* queue = (int*)malloc(n*sizeof(int));
 36     int front = -1, rear = -1;
 37     for(int i = 1; i <= n; i++){
 38         if(indegree[i] == 0){
 39             queue[++rear] = i;
 40         }
 41     }
 42     int cnt = 0;
 43     while(front < rear)
 44     {
 45         int v = queue[++front];
 46         cnt++;
 47         for(int i = 1; i <= n; i++){
 48             if(map[v][i] >= 0)
 49             {
 50                 indegree[i]--;
 51                 earliest[i] = max(earliest[i],earliest[v]+map[v][i]);
 52                 if(indegree[i] == 0){
 53                     queue[++rear] = i;
 54                 }
 55             }
 56         }
 57     }
 58     int ans = 0;
 59     if(cnt != n) ans = -1;
 60     else{
 61         ans = earliest[0];
 62         for(int i = 1; i <= n; i++){
 63             if(ans < earliest[i]) ans = earliest[i];
 64         }
 65     }
 66     return ans;
 67 }
 68 
 69 void late_time(int n,int x)
 70 {
 71     int* queue = (int*)malloc(n*sizeof(int));
 72     int front = -1,rear = -1;
 73     for(int i = n; i >= 1; i--){
 74         if(outdegree[i] == 0){
 75             queue[++rear] = i;
 76             latest[i] = x;
 77         }
 78     }
 79     while(front < rear){
 80         int v = queue[++front];
 81         for(int i = n; i >= 1; i--){
 82             if(map[i][v] >= 0){ /* 邻接边 */
 83                 outdegree[i]--;
 84                 latest[i] = min(latest[i],latest[v]-map[i][v]);
 85                 if(outdegree[i] == 0){
 86                     queue[++rear] = i;
 87                 }
 88             }
 89         }
 90     }
 91 }
 92 
 93 int main()
 94 {
 95     int n,m;
 96     scanf("%d%d",&n,&m);
 97     init(n); /* 初始化, n个任务交接点 */
 98     
 99     int v,u,w; /* m个子任务 */
100     for(int i = 0; i < m; i++){
101         scanf("%d%d%d",&u,&v,&w);
102         map[u][v] = w;
103         outdegree[u]++; /* 顶点的出度 */
104         indegree[v]++;  /* 顶点的入度  */
105     }
106     
107     int flag = early_time(n); /* 拓扑排序任务最早结束时间 */
108     if(flag == -1) printf("0\n");
109     else{
110         printf("%d\n",flag);
111         late_time(n,flag);    /* 拓扑排序任务最晚结束时间 */
112         for(int i = 1; i <= n; i++)
113         {
114             if(earliest[i] != latest[i]) 
115                 continue;
116             for(int j = n; j >= 1; j--)
117             {
118                 if(map[i][j] >= 0 &&  /* 单起点和单终点,2条关键路径 */
119                     earliest[j] == latest[j]&&  
120                     (latest[j] - earliest[i] == map[i][j]))/* 多起点多终点 */
121                         printf("%d->%d\n",i,j); 
122             }
123         }
124     }
125     return 0;
126 }

09-排序1 排序

给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。

本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:

数据1:只有1个元素;

数据2:11个不相同的整数,测试基本正确性;

数据3:103个随机整数;

数据4:104个随机整数;

数据5:105个随机整数;

数据6:105个顺序整数;

数据7:105个逆序整数;

数据8:105个基本有序的整数;

数据9:105个随机正整数,每个数字不超过1000。

输入格式:

输入第一行给出正整数N(≤105),随后一行给出N个(长整型范围内的)整数,其间以空格分隔。

输出格式:

在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。

输入样例:

11

4 981 10 -17 0 -20 29 50 8 43 -5

输出样例:

-20 -17 -5 0 4 8 10 29 43 50 981

 1 #include <stdio.h>
 2 #define MAXSIZE 100001
 3 
 4 typedef int ElementType;
 5 void Swap( ElementType *a, ElementType *b )
 6 {
 7      ElementType t = *a; *a = *b; *b = t;
 8 }
 9   
10 void PercDown( ElementType A[], int p, long N )
11 { /* 改编代码4.24的PercDown( MaxHeap H, int p )    */
12   /* 将N个元素的数组中以A[p]为根的子堆调整为最大堆 */
13     long Parent, Child;
14     ElementType X;
15  
16     X = A[p]; /* 取出根结点存放的值 */
17     for( Parent=p; (Parent*2+1)<N; Parent=Child ) {
18         Child = Parent * 2 + 1;
19         if( (Child!=N-1) && (A[Child]<A[Child+1]) )
20             Child++;  /* Child指向左右子结点的较大者 */
21         if( X >= A[Child] ) break; /* 找到了合适位置 */
22         else  /* 下滤X */
23             A[Parent] = A[Child];
24     }
25     A[Parent] = X;
26 }
27  
28 void HeapSort( ElementType A[], long N ) 
29 { /* 堆排序 */
30      long i;
31        
32      for ( i=N/2-1; i>=0; i-- )/* 建立最大堆 */
33          PercDown( A, i, N );
34       
35      for ( i=N-1; i>0; i-- ) {
36          /* 删除最大堆顶 */
37          Swap( &A[0], &A[i] ); 
38          PercDown( A, 0, i );
39      }
40 }
41 
42 int main()
43 {
44     long N;
45     int a[MAXSIZE] = {0};
46     scanf("%ld", &N);
47     for(long i=0; i<N; ++i){
48         scanf("%d",&a[i]);
49     }    
50     HeapSort(a,N);
51     for(long i=0; i<N; ++i){
52         if(i) printf(" ");
53         printf("%d",a[i]);
54     }        
55     return 0;
56 } 

09-排序2 Insert or Merge

According to Wikipedia:

Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain.

Merge sort works as follows: Divide the unsorted list into N sublists, each containing 1 element (a list of 1 element is considered sorted). Then repeatedly merge two adjacent sublists to produce new sorted sublists until there is only 1 sublist remaining.

Now given the initial sequence of integers, together with a sequence which is a result of several iterations of some sorting method, can you tell which sorting method we are using?

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤100). Then in the next line, N integers are given as the initial sequence. The last line contains the partially sorted sequence of the N numbers. It is assumed that the target sequence is always ascending. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in the first line either "Insertion Sort" or "Merge Sort" to indicate the method used to obtain the partial result. Then run this method for one more iteration and output in the second line the resuling sequence. It is guaranteed that the answer is unique for each test case. 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 1:

10

3 1 2 8 7 5 9 4 6 0

1 2 3 7 8 5 9 4 6 0

Sample Output 1:

Insertion Sort

1 2 3 5 7 8 9 4 6 0

Sample Input 2:

10

3 1 2 8 7 5 9 4 0 6

1 3 2 8 5 7 4 9 0 6

Sample Output 2:

Merge Sort

1 2 3 8 4 5 7 9 0 6

  1 #include <stdio.h>
  2 #include <stdbool.h>
  3 
  4 bool judge(int A[],int B[],int N)
  5 {
  6     for(int i=0;i<N;i++)
  7         if(A[i]!=B[i])
  8             return false;
  9     return true;
 10 }
 11 
 12 /* 插入排序  */
 13 bool Insertion_Sort(int A[],int B[],int N)
 14 {
 15     for(int P=1;P<N;P++)
 16     {
 17         int tmp = A[P];
 18         int j = P;
 19         for(;j>0 && tmp < A[j-1];j--)
 20             A[j] = A[j-1];
 21         A[j] = tmp;
 22         if(judge(A,B,N))
 23         {   /* 如果相等了,再做一轮 */ 
 24             P++;
 25             int tmp = A[P];
 26             int j = P;
 27             for(;j>0 && tmp < A[j-1];j--)
 28                 A[j] = A[j-1];
 29             A[j] = tmp;
 30             return true;
 31         }
 32     }
 33     return false; 
 34 }
 35 
 36 
 37 void Merge(int A[],int tmpA[],int L,int R,int RightEnd)
 38 {
 39     /* L = 左边起始位置,R = 右边起始位置,RightEnd = 右边终点位置  */
 40     int NumSize = RightEnd-L+1; /* 排序个数  */ 
 41     int LeftEnd = R-1;  /* 左边终止位置  */
 42     int tmp = L; 
 43     /* 排序 */ 
 44     while(L <= LeftEnd && R <= RightEnd){
 45         if(A[L] <= A[R])
 46             tmpA[tmp++] = A[L++];
 47         else
 48             tmpA[tmp++] = A[R++];
 49     } 
 50     /* 如果左边有剩  */
 51     while(L <= LeftEnd)
 52         tmpA[tmp++] = A[L++];
 53     /* 如果右边有剩  */
 54     while(R <= RightEnd)
 55         tmpA[tmp++] = A[R++];
 56     /* 导回 A 数组 */ 
 57     for(int i=0;i<NumSize;i++)
 58         A[RightEnd--] = tmpA[--tmp];
 59 }
 60 
 61 void Merge_pass(int A[],int tmpA[],int N,int length)
 62 {
 63     int i;
 64     /* 每次 2*length 为一组排序单元 */ 
 65     for(i=0;i<=N-2*length;i+=2*length)
 66         Merge(A,tmpA,i,i+length,i+length*2-1);
 67     /* 处理剩下的不够一组的排序单元 */ 
 68     if(i+length < N)   /* 如果左边够了,但是右边不齐,再次进入排序  */
 69         Merge(A,tmpA,i,i+length,N-1);
 70     else   /* 如果左边都不够,直接导给 tmpA  */
 71         for(int j=i;j<N;j++)
 72             tmpA[j] = A[j];            
 73 }
 74 
 75 /* 归并排序 */
 76 bool Merge_Sort(int A[],int B[],int N)
 77 {
 78     int tmpA[N];
 79     int length = 1;
 80     while(length < N){
 81         Merge_pass(A,tmpA,N,length);  /* 一趟归并 */ 
 82         length *=2;
 83         if(judge(A,B,N)){  /* 如果相等了,再做一轮  */
 84             Merge_pass(A,tmpA,N,length);
 85             return true;
 86         }
 87     } 
 88     return false;
 89 }
 90 
 91 /* 输出  */
 92 void output(int A[],int N)
 93 {
 94     for(int i=0;i<N;i++){
 95         if(i)
 96             printf(" ");
 97         printf("%d", A[i]); 
 98     } 
 99 } 
100 
101 int main()
102 {
103     int N;
104     scanf("%d", &N);
105     int A[N],tmpA[N];
106     for(int i=0;i<N;i++){
107         scanf("%d", &A[i]);
108         tmpA[i] = A[i];
109     }
110     int B[N];
111     for(int i=0;i<N;i++)
112         scanf("%d", &B[i]);
113     /* 用 tmpA 数组做归并排序,判断是否是归并排序  */
114     if(Merge_Sort(tmpA,B,N)){
115         printf("Merge Sort\n");
116         output(tmpA,N);
117     }
118     /* 用 A 数组做插入排序,判断是否是插入排序 */
119     else if(Insertion_Sort(A,B,N)){
120         printf("Insertion Sort\n");
121         output(A,N);
122     }
123     return 0;
124 }

09-排序3 Insertion or Heap Sort

According to Wikipedia:

Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain.

Heap sort divides its input into a sorted and an unsorted region, and it iteratively shrinks the unsorted region by extracting the largest element and moving that to the sorted region. it involves the use of a heap data structure rather than a linear-time search to find the maximum.

Now given the initial sequence of integers, together with a sequence which is a result of several iterations of some sorting method, can you tell which sorting method we are using?

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤100). Then in the next line, N integers are given as the initial sequence. The last line contains the partially sorted sequence of the N numbers. It is assumed that the target sequence is always ascending. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in the first line either "Insertion Sort" or "Heap Sort" to indicate the method used to obtain the partial result. Then run this method for one more iteration and output in the second line the resulting sequence. It is guaranteed that the answer is unique for each test case. 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 1:

10

3 1 2 8 7 5 9 4 6 0

1 2 3 7 8 5 9 4 6 0

Sample Output 1:

Insertion Sort

1 2 3 5 7 8 9 4 6 0

Sample Input 2:

10

3 1 2 8 7 5 9 4 6 0

6 4 5 1 0 3 2 7 8 9

Sample Output 2:

Heap Sort

5 4 3 1 0 2 6 7 8 9

  1 #include <stdio.h>
  2 #include <stdbool.h>
  3 
  4 /* 输出  */
  5 void output(int A[],int N)
  6 {
  7     for(int i=0;i<N;i++){
  8         if(i)
  9             printf(" ");
 10         printf("%d", A[i]); 
 11     } 
 12 } 
 13 
 14 bool judge(int A[],int B[],int N)
 15 {
 16     for(int i=0;i<N;i++)
 17         if(A[i]!=B[i])
 18             return false;
 19     return true;
 20 }
 21 
 22 /* 插入排序  */
 23 bool Insertion_Sort(int A[],int B[],int N)
 24 {
 25     for(int P=1;P<N;P++)
 26     {
 27         int tmp = A[P];
 28         int j = P;
 29         for(;j>0 && tmp < A[j-1];j--)
 30             A[j] = A[j-1];
 31         A[j] = tmp;
 32         if(judge(A,B,N))
 33         {   /* 如果相等了,再做一轮  */
 34             P++;
 35             int tmp = A[P];
 36             int j = P;
 37             for(;j>0 && tmp < A[j-1];j--)
 38                 A[j] = A[j-1];
 39             A[j] = tmp;
 40             return true;
 41         }
 42     }
 43     return false; 
 44 }
 45 
 46 typedef int ElementType;
 47 void Swap( ElementType *a, ElementType *b )
 48 {
 49      ElementType t = *a; *a = *b; *b = t;
 50 }
 51   
 52 void PercDown( ElementType A[], int p, int N )
 53 { /* 改编代码4.24的PercDown( MaxHeap H, int p )    */
 54   /* 将N个元素的数组中以A[p]为根的子堆调整为最大堆 */
 55     int Parent, Child;
 56     ElementType X;
 57  
 58     X = A[p]; /* 取出根结点存放的值 */
 59     for( Parent=p; (Parent*2+1)<N; Parent=Child ) {
 60         Child = Parent * 2 + 1;
 61         if( (Child!=N-1) && (A[Child]<A[Child+1]) )
 62             Child++;  /* Child指向左右子结点的较大者 */
 63         if( X >= A[Child] ) break; /* 找到了合适位置 */
 64         else  /* 下滤X */
 65             A[Parent] = A[Child];
 66     }
 67     A[Parent] = X;
 68 }
 69  
 70 bool HeapSort( ElementType A[], ElementType B[], int N ) 
 71 { /* 堆排序 */
 72      int i;
 73        
 74      for ( i=N/2-1; i>=0; i-- )/* 建立最大堆 */
 75          PercDown( A, i, N );
 76       
 77      for ( i=N-1; i>0; i-- ) {
 78          /* 删除最大堆顶 */
 79          Swap( &A[0], &A[i] ); 
 80          PercDown( A, 0, i );
 81          if(judge(A,B,N)){
 82              Swap( &A[0], &A[--i] ); 
 83              PercDown( A, 0, i );        
 84              return true;
 85          }
 86      }
 87      return false;
 88 }
 89 
 90 int main()
 91 {
 92     int N;
 93     scanf("%d", &N);
 94     int A[N],tmpA[N];
 95     for(int i=0;i<N;i++){
 96         scanf("%d", &A[i]);
 97         tmpA[i] = A[i];
 98     }
 99     int B[N];
100     for(int i=0;i<N;i++)
101         scanf("%d", &B[i]);
102     /* 用 A 数组做堆排序,判断是否是归并排序 */ 
103     if(HeapSort(tmpA,B,N)){
104         printf("Heap Sort\n");
105         output(tmpA,N);
106     }
107     /* 用 A 数组做插入排序,判断是否是插入排序 */
108     else if(Insertion_Sort(A,B,N)){
109         printf("Insertion Sort\n");
110         output(A,N);
111     }
112     return 0;
113 }

10-排序4 统计工龄

给定公司N名员工的工龄,要求按工龄增序输出每个工龄段有多少员工。

输入格式:

输入首先给出正整数N(≤105),即员工总人数;随后给出N个整数,即每个员工的工龄,范围在[0, 50]。

输出格式:

按工龄的递增顺序输出每个工龄的员工个数,格式为:“工龄:人数”。每项占一行。如果人数为0则不输出该项。

输入样例:

8

10 2 0 5 7 2 5 2

输出样例:

0:1

2:3

5:2

7:1

10:1

 1 #include <stdio.h>
 2 #define N 100001
 3 
 4 void bucket_sort(int A[],int n){
 5     int count[55] = {0};
 6     for(int i=0;i<n;i++)
 7         count[A[i]]++;
 8     for(int i=0;i<55;i++)
 9         if(count[i])
10             printf("%d:%d\n",i,count[i]);
11 }
12 
13 int main()
14 {
15     int A[N];
16     int n;
17     scanf("%d", &n);
18     for(int i=0;i<n;i++)
19         scanf("%d", &A[i]);
20     bucket_sort(A,n);
21     return 0;
22 }

10-排序5 PAT Judge

The ranklist of PAT is generated from the status list, which shows the scores of the submissions. This time you are supposed to generate the ranklist for PAT.

Input Specification:

Each input file contains one test case. For each case, the first line contains 3 positive integers, N (≤104), the total number of users, K (≤5), the total number of problems, and M (≤105), the total number of submissions. It is then assumed that the user id's are 5-digit numbers from 00001 to N, and the problem id's are from 1 to K. The next line contains K positive integers p[i] (i=1, ..., K), where p[i] corresponds to the full mark of the i-th problem. Then M lines follow, each gives the information of a submission in the following format:

user_id problem_id partial_score_obtained

where partial_score_obtained is either −1 if the submission cannot even pass the compiler, or is an integer in the range [0, p[problem_id]]. All the numbers in a line are separated by a space.

Output Specification:

For each test case, you are supposed to output the ranklist in the following format:

rank user_id total_score s[1] ... s[K]

where rank is calculated according to the total_score, and all the users with the same total_score obtain the same rank; and s[i] is the partial score obtained for the i-th problem. If a user has never submitted a solution for a problem, then "-" must be printed at the corresponding position. If a user has submitted several solutions to solve one problem, then the highest score will be counted.

The ranklist must be printed in non-decreasing order of the ranks. For those who have the same rank, users must be sorted in nonincreasing order according to the number of perfectly solved problems. And if there is still a tie, then they must be printed in increasing order of their id's. For those who has never submitted any solution that can pass the compiler, or has never submitted any solution, they must NOT be shown on the ranklist. It is guaranteed that at least one user can be shown on the ranklist.

Sample Input:

7 4 20

20 25 25 30

00002 2 12

00007 4 17

00005 1 19

00007 2 25

00005 1 20

00002 2 2

00005 1 15

00001 1 18

00004 3 25

00002 2 25

00005 3 22

00006 4 -1

00001 2 18

00002 1 20

00004 1 15

00002 4 18

00001 3 4

00001 4 2

00005 2 -1

00004 2 0

Sample Output:

1 00002 63 20 25 - 18

2 00005 42 20 0 22 -

2 00007 42 - 25 - 17

2 00001 42 18 18 4 2

5 00004 40 15 0 25

下一题预留空格

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值