zoukankan      html  css  js  c++  java
  • PTA(中国人民解放军陆军工程大学数据结构,C语言)

    7-1 数组循环左移

    本题要求实现一个对数组进行循环左移的简单函数:一个数组a中存有n(>)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥)个位置,即将a中的数据由(a​0​​a​1​​⋯a​n−1​​)变换为(a​m​​⋯a​n−1​​a​0​​a​1​​⋯a​m−1​​)(最前面的m个数循环移至最后面的m个位置)。如果还需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

    输入格式:

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

    输出格式:

    在一行中输出循环左移m位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

    输入样例:

    8 3

    1 2 3 4 5 6 7 8

    输出样例:

    4 5 6 7 8 1 2 3

     1 #include <stdio.h>
     2 #define N 100
     3 int main()
     4 {
     5     int i, n, k, arr[N] = {0}; 
     6     scanf("%d%d",&n,&k);
     7     /* 输入数组 */
     8     for(int i=0; i<n; ++i){
     9         scanf("%d,",&arr[i]);        
    10     }  
    11     /* 输出 */
    12     for(i=0; i<n-1; ++i){
    13         printf("%d ",arr[(i+k)%n]);
    14     } 
    15     printf("%d",arr[(i+k)%n]);
    16     return 0;
    17 }

    7-2 装箱问题

    假设有N项物品,大小分别为s​1​​、s​2​​、…、s​i​​、…、s​N​​,其中s​i​​为满足1的整数。要把这些物品装入到容量为100的一批箱子(序号1-N)中。装箱方法是:对每项物品, 顺序扫描箱子,把该物品放入足以能够容下它的第一个箱子中。请写一个程序模拟这种装箱过程,并输出每个物品所在的箱子序号,以及放置全部物品所需的箱子数目。

    输入格式:

    输入第一行给出物品个数N(≤);第二行给出N个正整数s​i​​(1,表示第i项物品的大小)。

    输出格式:

    按照输入顺序输出每个物品的大小及其所在的箱子序号,每个物品占1行,最后一行输出所需的箱子数目。

    输入样例:

    8

    60 70 80 90 30 40 10 20

    输出样例:

    60 1

    70 2

    80 3

    90 4

    30 1

    40 5

    10 1

    20 2

    5

     1 #include <stdio.h>
     2 #define N 1000
     3 struct node{
     4     int c;
     5     int cnt;
     6 };
     7 int main()
     8 {
     9     struct node a[N];
    10     int n, capacity = 100, count = 1;
    11     scanf("%d", &n);
    12     for(int i=0; i<n; ++i){
    13         scanf("%d",&a[i].c);
    14         a[i].cnt = 0;
    15     }
    16     for(int i= 0; i<n; ++i)
    17     {
    18         if(a[i].cnt) continue;
    19         int sum = a[i].c;
    20         a[i].cnt = count;
    21         for(int j=i+1; j<n; ++j){
    22             if(!a[j].cnt && sum+a[j].c <= capacity){
    23                 sum += a[j].c;
    24                 a[j].cnt = count;
    25             }        
    26         }
    27         count++;
    28     }
    29     for(int i=0; i<n; ++i){
    30         printf("%d %d
    ", a[i].c, a[i].cnt);
    31     }
    32     printf("%d
    ", count-1);    
    33     return 0;
    34 }

    7-3 两个有序序列的中位数

    已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列,的中位数指A​(N−1)/2​​的值,即第⌊个数(A​0​​为第1个数)。

    输入格式:

    输入分三行。第一行给出序列的公共长度N(0<N≤100000),随后每行输入一个序列的信息,即N个非降序排列的整数。数字用空格间隔。

    输出格式:

    在一行中输出两个输入序列的并集序列的中位数。

    输入样例1:

    5

    1 3 5 7 9

    2 3 4 5 6

    输出样例1:

    4

    输入样例2:

    6

    -100 -10 1 1 1 1

    -50 0 2 3 4 5

    输出样例2:

    1

     1 /* 算法1
     2 3个静态数组, 2个序列全部并入第3个序列 */
     3 #include <stdio.h>
     4 #define N 100000
     5 
     6 int main()
     7 {
     8     int a1[N], a2[N], c[2*N], cnt1=0, cnt2=0, cnt=0;
     9     int n;
    10     scanf("%d",&n);
    11     for(int i=0; i<n; ++i)
    12         scanf("%d",&a1[i]);
    13     for(int i=0; i<n; ++i)
    14         scanf("%d",&a2[i]);
    15     for(int i=0; cnt1<n && cnt2<n; ++i)
    16     {
    17         if(a1[cnt1]<=a2[cnt2]){
    18             c[cnt++] = a1[cnt1++];
    19         }
    20         else{
    21             c[cnt++] = a2[cnt2++];
    22         }
    23     }
    24     while(cnt1<n) c[cnt++] = a1[cnt1++];
    25     while(cnt2<n) c[cnt++] = a2[cnt2++];
    26     printf("%d
    ", c[(2*n-1)/2]);    
    27     return 0;
    28 }
     1 /*算法2
     2 三个动态数组, 2个序列并入第3个序列n个元素 
     3  */
     4 #include <stdio.h>
     5 #include <malloc.h>
     6 int main()
     7 {
     8     int* a1, *a2, *c;
     9     int cnt1=0, cnt2=0, cnt=0;
    10     int n;
    11     scanf("%d",&n);
    12     a1 = (int*)malloc(sizeof(int)*n);
    13     a2 = (int*)malloc(sizeof(int)*n);
    14     c = (int*)malloc(sizeof(int)*n);
    15     
    16     for(int i=0; i<n; ++i)
    17         scanf("%d",&a1[i]);
    18     for(int i=0; i<n; ++i)
    19         scanf("%d",&a2[i]);
    20     
    21     for(int i=0; i<n; ++i)
    22     {
    23         if(a1[cnt1]<=a2[cnt2]){
    24             c[cnt++] = a1[cnt1++];
    25         }
    26         else{
    27             c[cnt++] = a2[cnt2++];
    28         }
    29     }    
    30     
    31     printf("%d
    ", c[n-1]);    
    32     return 0;
    33 }
     1 /*算法3
     2 二个动态数组, 2个序列并入第3个序列n个元素 
     3  */
     4 #include <stdio.h>
     5 #include <malloc.h>
     6 int main()
     7 {
     8     int* a, *c;
     9     int cnt1=0, cnt2=0;
    10     int n;
    11     scanf("%d",&n);
    12     a = (int*)malloc(sizeof(int)*n*2);
    13     c = (int*)malloc(sizeof(int)*n);
    14     
    15     for(int i=0; i<n*2; ++i)
    16         scanf("%d",&a[i]);
    17     
    18     for(int i=0; i<n; ++i)
    19     {
    20         if(a[cnt1]<=a[n+cnt2]){
    21             c[i] = a[cnt1++];
    22         }
    23         else{
    24             c[i] = a[n+cnt2++];
    25         }
    26     }    
    27     
    28     printf("%d
    ", c[n-1]);    
    29     return 0;
    30 }
     1 /* 算法4
     2 2个动态数组, 不并, 通过下标计算中位数
     3  */
     4 #include <stdio.h>
     5 #include <malloc.h>
     6 int main()
     7 {
     8     int* a1, *a2;
     9     int cnt1=0, cnt2=0;    
    10     int n;
    11     scanf("%d",&n);
    12     a1 = (int*)malloc(sizeof(int)*n);
    13     a2 = (int*)malloc(sizeof(int)*n);
    14     
    15     for(int i=0; i<n; ++i)
    16         scanf("%d",&a1[i]);
    17     for(int i=0; i<n; ++i)
    18         scanf("%d",&a2[i]);
    19     
    20     while(cnt1+cnt2<(2*n-1)/2)
    21     {
    22         if(a1[cnt1]<=a2[cnt2]){
    23             cnt1++;
    24         }
    25         else{
    26             cnt2++;
    27         }
    28     }    
    29     printf("%d
    ", a1[cnt1]>a2[cnt2]?a2[cnt2]:a1[cnt1]);    
    30     return 0;
    31 }
    7-4 求链式线性表的倒数第K项 

    给定一系列正整数,请设计一个尽可能高效的算法,查找倒数第K个位置上的数字。

    输入格式:

    输入首先给出一个正整数K,随后是若干正整数,最后以一个负整数表示结尾(该负数不算在序列内,不要处理)。

    输出格式:

    输出倒数第K个位置上的数据。如果这个位置不存在,输出错误信息NULL

    输入样例:

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

    输出样例:

    7
     1 #include <stdio.h>
     2 #include <malloc.h>
     3 
     4 struct Node {
     5     int number;
     6     struct Node* next;
     7 };
     8 
     9 int main()
    10 {    
    11     int k;
    12     scanf("%d",&k);
    13     
    14     struct Node *p = NULL, *t = NULL; //p新结点, t当前结点
    15     int x;
    16     scanf("%d", &x);
    17     while(x >= 0)
    18     {        
    19         p = (struct Node*)malloc(sizeof(struct Node));
    20         p->number = x;
    21         p->next = NULL;    
    22        
    23         p->next = t, t = p;//头部插入更新当前t            
    24         scanf("%d",&x);
    25     }
    26     
    27     while(--k && p)
    28     {
    29         p = p->next;
    30     }
    31     
    32     if(p == NULL)
    33         printf("NULL
    ");
    34     else
    35         printf("%d
    ", p->number);
    36     
    37     return 0;
    38 }
    7-5 两个有序链表序列的交集 

    已知两个非降序链表序列S1与S2,设计函数构造出S1与S2的交集新链表S3。

    输入格式:

    输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−表示序列的结尾(−不属于这个序列)。数字用空格间隔。

    输出格式:

    在一行中输出两个输入序列的交集序列,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL

    输入样例:

    1 2 5 -1
    2 4 5 8 10 -1

    输出样例:

    2 5
     1 #include <stdio.h>
     2 #include <malloc.h>
     3 
     4 struct Node {
     5     int number;
     6     struct Node* next;
     7 };
     8 
     9 struct Node* CreatLinkList()
    10 {
    11     struct Node *h = NULL, *r = NULL, *p = NULL; 
    12     int x, flag = 1;
    13     while(scanf("%d", &x) && x >=0)
    14     {        
    15         p = (struct Node*)malloc(sizeof(struct Node));
    16         p->number = x;
    17         p->next = NULL;    
    18         if(flag) h = r = p;
    19         else r->next = p, r = p;//尾插
    20         flag = 0;
    21     }
    22     return h; 
    23 }
    24 
    25 int main()
    26 {  
    27     int flag = 1;
    28     struct Node *s1, *s2;
    29     s1 = CreatLinkList(), s2 = CreatLinkList();
    30     
    31     while(s1 && s2)
    32     {
    33         if(s1->number > s2->number)
    34             s2 = s2->next;            
    35         else if(s1->number < s2->number)
    36             s1 = s1->next;
    37         else{                             
    38             if(!flag)
    39                 printf(" ");
    40             printf("%d", s1->number);    
    41             s1 = s1->next;
    42             s2 = s2->next;
    43             flag = 0;
    44         }        
    45     }
    46     
    47     if(flag) printf("NULL
    ");
    48     
    49     return 0;
    50 }

    7-6 符号配对

    请编写程序检查C语言源程序中下列符号是否配对:/*与*/、(与)、[与]、{与}。

    输入格式:

    输入为一个C语言源程序。当读到某一行中只有一个句点.和一个回车的时候,标志着输入结束。程序中需要检查配对的符号不超过100个。

    输出格式:

    首先,如果所有符号配对正确,则在第一行中输出YES,否则输出NO。然后在第二行中指出第一个不配对的符号:如果缺少左符号,则输出?-右符号;如果缺少右符号,则输出左符号-?。

    输入样例1

    void test()
    {
        int i, A[10];
        for (i=0; i<10; i++) /*/
            A[i] = i;
    }
    .

    输出样例1:

    NO

    /*-?

    输入样例2:

    void test()
    {
        int i, A[10];
        for (i=0; i<10; i++) /**/
            A[i] = i;
    }]
    .

    输出样例2:

    NO

    ?-]

    输入样例3:

    void test()
    {
        int i
        double A[10];
        for (i=0; i<10; i++) /**/
            A[i] = 0.1*i;
    }
    .

    输出样例3:

    YES

     1 #include <stdio.h>
     2 #define N 100
     3 
     4 void printLeft(char ch) {//左字符打印
     5     if(ch == '<') printf("NO
    /*-?
    ");
     6     else printf("NO
    %c-?
    ", ch);
     7 }
     8 
     9 void printRight(char ch) {//右字符打印
    10     if(ch == '<') printf("NO
    ?-*/
    ");    
    11     else  printf("NO
    ?-%c
    ",ch);
    12 }
    13 
    14 int charMatch(char ch1,char ch2)//字符匹配
    15 {    
    16     return ch1=='(' && ch2==')' 
    17             || ch1=='[' && ch2==']'
    18             ||ch1=='{' && ch2=='}'
    19             ||ch1 == ch2;    
    20 }
    21 
    22 int MatchOrPrint(char ch1, int* top, int flag, char ch2)
    23 {
    24     if(*top != -1 && charMatch(ch1,ch2)){
    25         (*top)--;  //栈有字符且匹配出栈
    26     }     
    27     else //栈无字符或不匹配
    28     {                    
    29         flag = 0; //栈无字符或不匹配
    30         if(*top == -1) {//1.栈无字符(缺左打右)
    31             printRight(ch2);
    32         }
    33         else { //2.栈有字符(缺右打左)
    34             printLeft(ch1);
    35         }
    36     }
    37     return flag;
    38 }
    39 
    40 int main() 
    41 {
    42     char str[10*N];//字符串
    43     char stack[N]; //
    44     int i, top = -1, flag = 1;//flag匹配标志
    45 
    46     while(gets(str) && str[0] != '.')//按行读入
    47     {        
    48         for( i = 0; str[i]; i++) //逐行处理 
    49         {   
    50             if(str[i] == '(' || str[i] == '[' || str[i] == '{') 
    51             {
    52                 stack[++top] = str[i]; //左符号入栈
    53             }
    54             else if(str[i] == '/' && str[i + 1] == '*') 
    55             {
    56                 stack[++top] = '<'; //左符号入栈
    57                 i++;
    58             }            
    59             else if(str[i] == '*' && str[i + 1] == '/') 
    60             {                  
    61                 flag = MatchOrPrint(stack[top], &top, flag, '<');
    62                 i++; // 处理右*/避免'/'再次处理, for循环再次++
    63             }
    64             else if(str[i] == ')'||str[i] == ']'||str[i] == '}')
    65             {   //处理右 ')', ']', '}'
    66                 flag = MatchOrPrint(stack[top], &top, flag, str[i]);
    67             }
    68             if(flag == 0) break;//栈无字符或不匹配
    69         }
    70         if(flag == 0) break; //栈无字符或不匹配
    71     }
    72     
    73     if(flag && top == -1) printf("YES
    ");//栈空且左右匹配
    74     else if(flag) { //即使左右匹配栈不空(缺右打左)
    75         printLeft(stack[top]);
    76     } 
    77     return 0;
    78 }

    7-7 整型关键字的散列映射

    给定一系列整型关键字和素数P,用除留余数法定义的散列函数将关键字映射到长度为P的散列表中。用线性探测法解决冲突。

    输入格式:

    输入第一行首先给出两个正整数N(≤)和P(≥的最小素数),分别为待插入的关键字总数、以及散列表的长度。第二行给出N个整型关键字。数字间以空格分隔。

    输出格式:

    在一行内输出每个整型关键字在散列表中的位置。数字间以空格分隔,但行末尾不得有多余空格。

    输入样例:

    4 5

    24 15 61 88

    输出样例:

    4 0 1 3

     1 #include <stdio.h>
     2 #include <malloc.h>
     3 int main() 
     4 {
     5     int n, p;
     6     scanf( "%d%d", &n, &p );
     7     int* table = (int*)calloc(p, sizeof(int)); //散列表    
     8     int x;
     9     for( int i = 0; i < n; i++ ) 
    10     {
    11         scanf( "%d", &x );     
    12         int index = x % p;
    13         while( table[index] ){    
    14             if(table[index] == x)//重复数字
    15                 break;
    16            index = (index+1)%p;            
    17         }
    18         table[index] = x;//在散列表的index位置记录x      
    19         if( i == 0 ) printf( "%d", index );
    20         else printf( " %d", index );
    21     } 
    22     return 0;
    23 }

    7-8 树的遍历

    给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

    输入格式:

    输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

    输出格式:

    在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

    输入样例:

    7

    2 3 1 5 7 6 4

    1 2 3 4 5 6 7

    输出样例:

    4 1 6 3 5 7 2

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <stdbool.h>
      4 #include <malloc.h>
      5 #define ERROR -1
      6 #define N 31
      7 
      8 /* 二叉树结点 */
      9 typedef struct TreeNode *BinTree;
     10 struct TreeNode{
     11     int Data;
     12     BinTree Left;
     13     BinTree Right;
     14 };
     15 
     16 /* 创建树结点 */
     17 BinTree NewNode( int V )
     18 { 
     19     BinTree T = (BinTree)malloc(sizeof(struct TreeNode));
     20     T->Data = V;
     21     T->Left = T->Right = NULL;
     22     return T;
     23 }
     24 
     25 /* 建树 */
     26 BinTree  BuildTree(int a[],int b[],int i,int j,int s,int e) 
     27 {   /* i,j树的后序序列的起止, s,e树的中序序列的起止 */
     28     int k; 
     29     BinTree p;
     30     if( i > j )    return NULL;//递归终止
     31     
     32     p = NewNode(a[j]); //后序的根a[j]创建结点
     33     
     34     k = s;  /* 寻找树根位置 */
     35     while( ( k <= e ) && ( b[k] != a[j] ) )    k++; 
     36     
     37     if( k > e )    exit(ERROR); 
     38     
     39     p->Left  = BuildTree(a, b, i, i+(k-s)-1, s, k-1); /* 左子树 */   
     40     p->Right = BuildTree(a, b, i+(k-s), j-1, k+1, e); /* 右子树 */    
     41     return p;
     42 }
     43 
     44 /* 顺序循环队列*/
     45 typedef struct QNode *Queue; /* 队列指针 */
     46 struct QNode {
     47     BinTree* Data;     /* 存储元素的数组 */
     48     int Front, Rear;  /* 队列的头、尾指针 */
     49     int MaxSize;           /* 队列最大容量 */
     50 };
     51 
     52  /* 建队列 */
     53 Queue CreateQueue( int MaxSize )
     54 {
     55     Queue Q = (Queue)malloc(sizeof(struct QNode));
     56     Q->Data = (BinTree*)malloc(MaxSize * sizeof(BinTree));
     57     Q->Front = Q->Rear = 0;
     58     Q->MaxSize = MaxSize;
     59     return Q;
     60 }
     61 
     62 /* 队满 */
     63 bool IsFull( Queue Q )
     64 {
     65     return ((Q->Rear+1)%Q->MaxSize == Q->Front);
     66 }
     67 
     68 /* 队空 */
     69 bool IsEmpty( Queue Q )
     70 {
     71     return (Q->Front == Q->Rear);
     72 }
     73 
     74 /* 入队 */
     75 bool AddQ( Queue Q, BinTree X )
     76 {
     77     if ( IsFull(Q) ) {
     78         return false;
     79     }
     80     else {
     81         Q->Rear = (Q->Rear+1)%Q->MaxSize;
     82         Q->Data[Q->Rear] = X;
     83         return true;
     84     }
     85 }
     86 
     87 /* 出队 */
     88 BinTree DeleteQ( Queue Q )
     89 {    
     90     if ( IsEmpty(Q) )
     91         return NULL;
     92     Q->Front =(Q->Front+1)%Q->MaxSize;
     93     return  Q->Data[Q->Front];   
     94 }
     95 
     96 /* 层序遍历 */
     97 void LevelorderTraversal ( BinTree BT )
     98 { 
     99     Queue Q; 
    100     BinTree T;
    101  
    102     if ( !BT ) return; /* 若是空树则直接返回 */
    103      
    104     Q = CreateQueue(N); /* 创建空队列Q */
    105     AddQ( Q, BT ); /* 树根入队 */
    106     
    107     int flag = 0;  /* 控制输出空格 */
    108     
    109     while ( !IsEmpty(Q) ) 
    110     {
    111         T = DeleteQ( Q );
    112         if(flag) printf(" ");
    113         flag = 1;
    114         printf("%d", T->Data); /* 访问取出队列的结点 */
    115         if ( T->Left )   AddQ( Q, T->Left );  /* 左子树入队 */
    116         if ( T->Right )  AddQ( Q, T->Right ); /* 右子树入队 */
    117     }
    118 }
    119 int main()
    120 {    
    121     int a[N] = {0}, b[N] = {0};
    122     int n;
    123     scanf("%d", &n);
    124     /* 输入树的后序遍历中序遍历序列 */
    125     for(int i=0; i<n; ++i)
    126     {
    127         scanf("%d", &a[i]);
    128     }
    129     for(int i=0; i<n; ++i)
    130     {
    131         scanf("%d", &b[i]);
    132     }
    133     /* 恢复树 */
    134     BinTree root = BuildTree(a, b , 0, n-1 , 0,  n-1); 
    135     /* 层序遍历输出 */
    136     LevelorderTraversal(root);
    137     
    138     return 0; 
    139 }

    7-9 根据后序和中序遍历输出先序遍历

    本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的先序遍历结果。

    输入格式:

    第一行给出正整数N(≤30),是树中结点的个数。随后两行,每行给出N个整数,分别对应后序遍历和中序遍历结果,数字间以空格分隔。题目保证输入正确对应一棵二叉树。

    输出格式:

    在一行中输出Preorder:以及该树的先序遍历结果。数字间有1个空格,行末不得有多余空格。

    输入样例:

    7

    2 3 1 5 7 6 4

    1 2 3 4 5 6 7

    输出样例:

    Preorder: 4 1 3 2 6 5 7

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <stdbool.h>
     4 #include <malloc.h>
     5 #define ERROR -1
     6 #define N 31
     7 
     8 /* 二叉树结点 */
     9 typedef struct TreeNode *BinTree;
    10 struct TreeNode{
    11     int Data;
    12     BinTree Left;
    13     BinTree Right;
    14 };
    15 
    16 typedef BinTree Stack; /* 栈类型 */
    17 
    18 /* 创建树结点 */
    19 BinTree NewNode( int V )
    20 { 
    21     BinTree T = (BinTree)malloc(sizeof(struct TreeNode));
    22     T->Data = V;
    23     T->Left = T->Right = NULL;
    24     return T;
    25 }
    26 
    27 /* 建树 */
    28 BinTree  BuildTree(int a[],int b[],int i,int j,int s,int e) 
    29 {   /* i,j树的后序序列的起止, s,e树的中序序列的起止 */
    30     int k; 
    31     BinTree p;
    32     if( i > j )    return NULL;//递归终止
    33     
    34     p = NewNode(a[j]); //后序的根a[j]创建结点
    35     
    36     k = s;  /* 寻找树根位置 */
    37     while( ( k <= e ) && ( b[k] != a[j] ) )    k++; 
    38     
    39     if( k > e )    exit(ERROR); 
    40     
    41     p->Left  = BuildTree(a, b, i, i+(k-s)-1, s, k-1); /* 左子树 */   
    42     p->Right = BuildTree(a, b, i+(k-s), j-1, k+1, e); /* 右子树 */    
    43     return p;
    44 }
    45 
    46 /* 非递归先序遍历 */
    47 void PreorderTraversal( BinTree BT )
    48 { 
    49     BinTree T = BT;
    50     Stack S[N]; /* 建栈 */
    51     int top = -1;
    52     while( T || top != -1 )/* 树不空或栈不空 */
    53     {
    54         while(T)/*一直向左并将沿途结点压入堆栈*/
    55         { 
    56             S[++top] = T;  /* 结点压栈(第一次遇到结点) */
    57             printf(" %d", T->Data); /*(访问)打印结点*/
    58             T = T->Left;/* 一直向左 */
    59         }
    60         if(top != -1) /* 栈不空 */
    61         {
    62             T = S[top--];  /*结点弹出堆栈(第二次遇到结点)*/            
    63             T = T->Right;/*转向右子树*/
    64         }
    65     }
    66 }
    67 
    68 int main()
    69 {    
    70     int a[N] = {0}, b[N] = {0};
    71     int n;
    72     scanf("%d", &n);
    73     /* 输入树的后序遍历中序遍历序列 */
    74     for(int i=0; i<n; ++i)
    75     {
    76         scanf("%d", &a[i]);
    77     }
    78     for(int i=0; i<n; ++i)
    79     {
    80         scanf("%d", &b[i]);
    81     }
    82     /* 恢复树 */
    83     BinTree root = BuildTree(a, b , 0, n-1 , 0,  n-1); 
    84     /* 先序遍历输出 */
    85     printf("Preorder:");
    86     PreorderTraversal(root);
    87     
    88     return 0; 
    89 }

    7-10 是否完全二叉搜索树

    将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果。

    输入格式:

    输入第一行给出一个不超过20的正整数N;第二行给出N个互不相同的正整数,其间以空格分隔。

    输出格式:

    将输入的N个正整数顺序插入一个初始为空的二叉搜索树。在第一行中输出结果树的层序遍历结果,数字间以1个空格分隔,行的首尾不得有多余空格。第二行输出YES,如果该树是完全二叉树;否则输出NO。

    输入样例1:

    9

    38 45 42 24 58 30 67 12 51

    输出样例1:

    38 45 24 58 42 30 12 67 51

    YES

    输入样例2:

    8

    38 24 12 45 58 67 42 51

    输出样例2:

    38 45 24 58 42 12 67 51

    NO

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <stdbool.h>
      4 
      5 /* 树结点 */
      6 typedef struct TreeNode *BinTree;
      7 typedef struct TreeNode TreeNode;
      8 struct TreeNode{
      9     int Data, ID;
     10     BinTree Left;
     11     BinTree Right;
     12 };
     13 
     14 /* 顺序循环队列*/
     15 #define MAXSIZE  21 //最大队列长度 N 
     16 typedef struct QNode *Queue; 
     17 struct QNode {
     18     BinTree* Data;    /* 存储元素的数组 */
     19     int Front, Rear;  /* 队列的头、尾指针 */
     20     int MaxSize;      /* 队列最大容量 */
     21 };
     22 
     23 BinTree Insert( BinTree BST, int X );     /* 插入 */
     24 void LevelorderTraversal ( BinTree BT );  /* 层次遍历 */
     25 Queue CreateQueue( );                /*  建队 */
     26 bool IsFull( Queue Q );              /* 队满 */
     27 bool IsEmpty( Queue Q );             /* 队空 */
     28 bool AddQ( Queue Q, BinTree X );     /* 入队 */
     29 BinTree DeleteQ( Queue Q );             /* 出队 */
     30 
     31 int main()
     32 {
     33     int N, i, X;   
     34     scanf("%d", &N);
     35     
     36     BinTree BST = NULL;
     37     for ( i=0; i<N; i++ ) {
     38         scanf("%d", &X);
     39         BST = Insert(BST, X);
     40     }
     41     LevelorderTraversal(BST);
     42     return 0;
     43 }
     44 
     45 BinTree Insert( BinTree BST, int X )
     46 {
     47     if(!BST)
     48     {  
     49         BST = (BinTree)malloc(sizeof(TreeNode));
     50         BST->Data = X;
     51         BST->Left = NULL;
     52         BST->Right = NULL;
     53     }
     54     else
     55     {
     56         if(X > BST->Data)
     57             BST->Left = Insert(BST->Left,X);
     58         else if(BST->Data > X)
     59             BST->Right = Insert(BST->Right,X);
     60     }
     61     return BST; 
     62 }
     63 
     64 void LevelorderTraversal ( BinTree BT )
     65 { 
     66     Queue Q; 
     67     BinTree T;
     68     
     69     bool flag = true, ans = true;
     70     int order = 0; /* 顺序 */
     71     
     72     if ( !BT ) return; /* 若是空树则直接返回 */
     73     
     74     Q = CreateQueue(); /* 创建空队列Q */ 
     75     
     76     
     77     AddQ( Q, BT ); /* 树根入队 */
     78     BT->ID = 1;
     79     
     80     while ( !IsEmpty(Q) ) 
     81     {
     82         T = DeleteQ( Q ); /* 出队 */
     83         order++;
     84         
     85         if(T->ID != order)
     86             ans = false; /* 顺序不同 */
     87         if(flag)  /* 输出格式 */
     88         {
     89             printf("%d", T->Data);
     90             flag = false;
     91         }
     92         else printf(" %d", T->Data);
     93               
     94         if ( T->Left ){
     95             T->Left->ID = 2 * T->ID;  /* 左儿子顺序 */
     96             AddQ( Q, T->Left );       /* 左儿子入队 */
     97         }   
     98         if ( T->Right ){
     99             T->Right->ID = 2 * T->ID + 1;/* 右儿子顺序 */
    100             AddQ( Q, T->Right );         /* 右儿子入队 */
    101         }  
    102     }
    103     
    104     if(ans)  /* 顺序相同 */
    105         printf("
    YES");
    106     else
    107         printf("
    NO"); 
    108 }
    109 
    110  /* 建队列 */
    111 Queue CreateQueue( )//返回队列指针
    112 {
    113     Queue Q = (Queue)malloc(sizeof(struct QNode));
    114     Q->Data = (BinTree*)malloc(MAXSIZE * sizeof(BinTree));
    115     Q->Front = Q->Rear = 0;
    116     Q->MaxSize = MAXSIZE;
    117     return Q;
    118 }
    119 
    120 /* 队满 */
    121 bool IsFull( Queue Q )
    122 {
    123     return ((Q->Rear+1)%Q->MaxSize == Q->Front);
    124 }
    125 
    126 /* 队空 */
    127 bool IsEmpty( Queue Q )
    128 {
    129     return (Q->Front == Q->Rear);
    130 }
    131 
    132 /* 入队 */
    133 bool AddQ( Queue Q, BinTree X )
    134 {
    135     if ( IsFull(Q) ) {
    136         return false;
    137     }
    138     else {
    139         Q->Rear = (Q->Rear+1)%Q->MaxSize;
    140         Q->Data[Q->Rear] = X;
    141         return true;
    142     }
    143 }
    144 
    145 /* 出队 */
    146 BinTree DeleteQ( Queue Q )
    147 {    
    148     if ( IsEmpty(Q) )
    149         return NULL;
    150     Q->Front =(Q->Front+1)%Q->MaxSize;
    151     return  Q->Data[Q->Front];   
    152 }

    7-11 修理牧场

    农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li的总和。但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。

    请编写程序帮助农夫计算将木头锯成N块的最少花费。

    输入格式:

    输入首先给出正整数N(≤104),表示要将木头锯成N块。第二行给出N个正整数(≤50),表示每段木块的长度。

    输出格式:

    输出一个整数,即将木头锯成N块的最少花费。

    输入样例:

    8

    4 5 1 2 1 3 1 1

    输出样例:

    49

      1 /* 
      2     建一个最小堆, 堆插入树结点, 形成树结点森林;
      3     每次从堆中取2个最小树结点, 建中间树结点并插入堆;
      4     (最后堆中森林形成一棵Huffman树)
      5     打印Huffman树的WPL; 
      6 */
      7 
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 
     11 /* 二叉树结点 */
     12 typedef struct TreeNode* Tree;
     13 struct TreeNode {
     14     int Weight;
     15     Tree Left, Right;
     16 };
     17 
     18 /* 堆(优先队列) */
     19 #define MAXSIZE 10001 
     20 typedef struct HeapNode* Heap;
     21 struct HeapNode {   
     22     struct TreeNode Data[MAXSIZE];/* 完全二叉树顺序存储 */
     23     int Size;
     24 };
     25  
     26  /* 建树结点 */
     27 Tree NewTreeNode() {
     28     Tree T;
     29     T = (Tree)malloc(sizeof(struct TreeNode));
     30     T->Weight = 0;
     31     T->Left = T->Right = NULL;    
     32     return T;
     33 }
     34 
     35  /* 建空堆 */
     36 Heap CreatHeap() {
     37     Heap H;
     38     H = (Heap)malloc(sizeof(struct HeapNode));
     39     H->Size = 0;            /* 空堆 */
     40     H->Data[0].Weight = -1; /* 哨兵 */
     41     return H;
     42 }
     43  
     44  /* 堆插入 */
     45 void Insert(Heap H, struct TreeNode T) {
     46     int i = ++H->Size;  /* ++堆, 从堆的最后开始寻找插入结点位置 */
     47     for( ; T.Weight < H->Data[i/2].Weight; i /= 2)
     48         H->Data[i] = H->Data[i/2]; /* 父结点下滤 */
     49     H->Data[i] = T; /* 插入结点 */
     50 }
     51 
     52  /* 堆删除 */
     53 Tree Delete(Heap H) 
     54 {    /* 提取堆最后一个树结点, 从堆的第一个结点开始比较,上滤, 堆-- */
     55     int parent, child;
     56     struct TreeNode Temp = H->Data[H->Size--]; /* 提取堆最后一个树结点 */
     57     Tree T = NewTreeNode(); /* 创建树结点 */
     58     *T = H->Data[1];        /* 从堆中提取第一个树结点 */
     59     for(parent = 1; 2*parent <= H->Size; parent = child) 
     60     {
     61         child = 2 * parent; /* 从父结点找左孩子 */
     62         if(child != H->Size && H->Data[child].Weight > H->Data[child+1].Weight) 
     63             child++;        /* 有右孩子且比左孩子小, 选右孩子 */
     64         if(Temp.Weight < H->Data[child].Weight) 
     65             break;  /* 原堆最后一个树结点找到位置 */
     66         H->Data[parent] = H->Data[child]; /* 孩子结点上滤, 孩子结点覆盖父结点 */
     67     }
     68     H->Data[parent] = Temp; /* 原堆最后一个树结点归位 */
     69     return T; /* 返回原堆第一个树结点 */
     70 }
     71 
     72 /* 建Huffman树 */
     73 Tree Huffman(Heap H) 
     74 {   
     75     Tree T = NewTreeNode(); /* 临时树结点 */
     76     while(H->Size != 1) 
     77     {    /* 每次取堆中2个最小值建中间树结点 */
     78         T->Left = Delete(H);  
     79         T->Right = Delete(H);
     80         T->Weight = T->Left->Weight + T->Right->Weight;
     81         
     82         Insert(H, *T); /* 复制创建的中间树结点(传参)插入堆 */
     83     }
     84     free(T); /* 释放临时结点 */
     85     T = Delete(H); /* 取出堆中的树 */
     86     return T;
     87 }
     88  
     89 int WPL(Tree T, int Depth) { /* 整棵树的WPL */
     90     if(!T->Left && !T->Right) {  return Depth*T->Weight; }
     91     else return WPL(T->Left, Depth+1) + WPL(T->Right, Depth+1);
     92 }
     93  
     94 int main() 
     95 {
     96     int N, Weight;
     97    
     98     Heap H = CreatHeap(); /* 建空堆 */
     99     Tree T = NewTreeNode();  /* 建临时树结点 */
    100     
    101     scanf("%d", &N);  /* 树结点个数 */
    102     for(int i = 0; i < N; i++) 
    103     {      
    104         scanf("%d", &Weight);        
    105         T->Weight = Weight;
    106         H->Data[H->Size].Left = H->Data[H->Size].Right = NULL;       
    107         Insert(H, *T); /* 复制创建的树结点(传参), 插入堆, 形成树森林 */
    108     }
    109     
    110     free(T); /* 释放临时结点 */
    111     
    112     T = Huffman(H);   /* 建Huffman树  */
    113     
    114     printf("%d
    ", WPL(T, 0)); /* 输出Huffman树的WPL */
    115     
    116     return 0;
    117 }

    7-12 地下迷宫探索

    地道战是在抗日战争时期,在华北平原上抗日军民利用地道打击日本侵略者的作战方式。地道网是房连房、街连街、村连村的地下工事,如下图所示。

    我们在回顾前辈们艰苦卓绝的战争生活的同时,真心钦佩他们的聪明才智。在现在和平发展的年代,对多数人来说,探索地下通道或许只是一种娱乐或者益智的游戏。本实验案例以探索地下通道迷宫作为内容。

    假设有一个地下通道迷宫,它的通道都是直的,而通道所有交叉点(包括通道的端点)上都有一盏灯和一个开关。请问你如何从某个起点开始在迷宫中点亮所有的灯并回到起点?

    输入格式:

    输入第一行给出三个正整数,分别表示地下迷宫的节点数N(1<N≤1000,表示通道所有交叉点和端点)、边数M(≤3000,表示通道数)和探索起始节点编号S(节点从1到N编号)。随后的M行对应M条边(通道),每行给出一对正整数,分别是该条边直接连通的两个节点的编号。

    输出格式:

    若可以点亮所有节点的灯,则输出从S开始并以S结束的包含所有节点的序列,序列中相邻的节点一定有边(通道);否则虽然不能点亮所有节点的灯,但还是输出点亮部分灯的节点序列,最后输出0,此时表示迷宫不是连通图。

    由于深度优先遍历的节点序列是不唯一的,为了使得输出具有唯一的结果,我们约定以节点小编号优先的次序访问(点灯)。在点亮所有可以点亮的灯后,以原路返回的方式回到起点。

    输入样例1:

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

    输出样例1:

    1 2 3 4 5 6 5 4 3 2 1

    输入样例2:

    6 6 6
    1 2
    1 3
    2 3
    5 4
    6 5
    6 4

    输出样例2:

    6 4 5 4 6 0
     1 #include <stdio.h>
     2 
     3 #define MAXN 1010  /* 最大结点数 */
     4 int AdjMatrix[MAXN][MAXN] = {0}; /* 邻接矩阵 */
     5 int visited[MAXN] = {0}; /* 访问标记 */
     6 int flag = 0;
     7 int count = 1; /* 入口1 */
     8 int n;  /* 结点数 */
     9  
    10 void DFS(int s)
    11 {
    12     if(flag)
    13         printf(" ");
    14     flag++;
    15     printf("%d", s);  /* 访问 */
    16     visited[s] = 1;
    17     for(int i = 1;i<=n;i++) /* 结点序号从1开始到n */
    18         if(!visited[i]&&AdjMatrix[s][i]) /* 结点没访问且有边 */
    19         {
    20             count++;         /* 访问结点计数 */
    21             DFS(i);             /* 递归调用 */
    22             printf(" %d",s); /* 返回 */
    23         }
    24 }
    25  
    26 int main()
    27 {
    28     int m,s;  
    29     scanf("%d%d%d", &n, &m, &s); /* 结点数 边数 入口 */
    30     for(int i = 0;i<m;i++)
    31     {
    32         int a,b;        /* 边的两个结点编号 */
    33         scanf("%d%d", &a, &b); 
    34         AdjMatrix[a][b] = AdjMatrix[b][a] = 1;
    35     }
    36     DFS(s);     /* 深度搜索 */
    37     if(count<n) /* 迷宫不连通 */
    38         printf(" 0");
    39     return 0;
    40 }

    7-13 畅通工程之局部最小花费问题

    某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建快速路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全地区畅通需要的最低成本。

    输入格式:

    输入的第一行给出村庄数目N (1≤N≤100);随后的N(N−1)/2行对应村庄间道路的成本及修建状态:每行给出4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态 — 1表示已建,0表示未建。

    输出格式:

    输出全省畅通需要的最低成本。

    输入样例:

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

    输出样例:

    3
     1 #include <stdio.h>
     2 
     3 #define inf 65535
     4 #define MAXN 200
     5 int map[MAXN][MAXN],w[MAXN],visit[MAXN];
     6 int N;
     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,state,k = N*(N-1)/2;
    16     for(int i = 0; i<k; i++) 
    17     { /* 两个村庄start,end,村庄之间路的花费cost,是否已修建state */
    18         scanf("%d%d%d%d",&start,&end,&cost,&state);
    19         if(state == 0) {
    20             map[start][end] = cost;
    21             map[end][start] = cost;
    22         } else {
    23             map[start][end] = 0;
    24             map[end][start] = 0;
    25         }
    26     }
    27 }
    28 
    29 void prim() 
    30 {    /* 从1顶点出开始生成最小生成树 */
    31     for(int i = 1; i<=N; i++){
    32         visit[i] = 0;
    33         if(i != 1)
    34             w[i] = map[1][i];
    35     }
    36     visit[1] = 1;
    37     int pos = 0,MIN = inf;
    38     for(int i = 0; i<N; i++) 
    39     {
    40         MIN = inf,pos = 0;
    41         for(int j = 1; j<=N; j++) 
    42         {/* 从没有访问过的顶点中找到下一个距离最短的边 */
    43             if(!visit[j] && MIN>w[j]) {
    44                 MIN = w[j];
    45                 pos = j;
    46             }
    47         }
    48         visit[pos] = 1;
    49         for(int j = 1; j<=N; j++) 
    50         {  /* 用这个最小的顶点的邻接边的权值更新w[]的值 */
    51             if(!visit[j] && map[pos][j]<w[j]) {
    52                 w[j] = map[pos][j];
    53             }
    54         }
    55     }
    56 }
    57 
    58 int main() 
    59 {
    60     scanf("%d",&N);
    61     init();
    62     prim();
    63 
    64     int sum = 0;
    65     /* 最低成本 */
    66     for(int i = 1; i<=N; i++) {
    67         sum += w[i];
    68     }
    69     printf("%d
    ",sum);
    70     return 0;
    71 }

    7-14 奥运排行榜

    每年奥运会各大媒体都会公布一个排行榜,但是细心的读者发现,不同国家的排行榜略有不同。比如中国金牌总数列第一的时候,中国媒体就公布“金牌榜”;而美国的奖牌总数第一,于是美国媒体就公布“奖牌榜”。如果人口少的国家公布一个“国民人均奖牌榜”,说不定非洲的国家会成为榜魁…… 现在就请你写一个程序,对每个前来咨询的国家按照对其最有利的方式计算它的排名。

    输入格式:

    输入的第一行给出两个正整数N和M(≤224,因为世界上共有224个国家和地区),分别是参与排名的国家和地区的总个数、以及前来咨询的国家的个数。为简单起见,我们把国家从0 ~ N−1编号。之后有N行输入,第i行给出编号为i−1的国家的金牌数、奖牌数、国民人口数(单位为百万),数字均为[0,1000]区间内的整数,用空格分隔。最后面一行给出M个前来咨询的国家的编号,用空格分隔。

    输出格式:

    在一行里顺序输出前来咨询的国家的排名:计算方式编号。其排名按照对该国家最有利的方式计算;计算方式编号为:金牌榜=1,奖牌榜=2,国民人均金牌榜=3,国民人均奖牌榜=4。输出间以空格分隔,输出结尾不能有多余空格。

    若某国在不同排名方式下有相同名次,则输出编号最小的计算方式。

    输入样例:

    4 4
    51 100 1000
    36 110 300
    6 14 32
    5 18 40
    0 1 2 3

    输出样例:

    1:1 1:2 1:3 1:4
    #include <stdio.h>
    
    #define MAXN 225  /* 224个国家 */
    struct country
    {
        int gold;  /* 金牌 */
        int medal; /* 奖牌 */
        int pop;   /* 人口数population */
    } cts[MAXN];   /* 城市数 */
    
    int main()
    {
        int m,n;
        scanf("%d %d",&n,&m);   /* 参与总数n,咨询总数m */
        for(int i = 0; i < n; i++) /* 参与 */
        {
            scanf("%d %d %d",&cts[i].gold,&cts[i].medal,&cts[i].pop);
        }
        for(int i = 0; i < m; i++)  /* m个国家咨询 */
        {
            int num;
            scanf("%d",&num); /* 咨询国家编号num */
            int rank[4] = {0};        /* 4种计算名次方法 */
            
            for(int i = 0; i < n; i++) /* 计算名次 */
            {
                if(cts[i].gold > cts[num].gold)
                    rank[0]++;
                if(cts[i].medal > cts[num].medal)
                    rank[1]++;
                if(cts[i].gold*cts[num].pop > cts[num].gold*cts[i].pop)
                    rank[2]++;
                if(cts[i].medal*cts[num].pop > cts[num].medal*cts[i].pop)
                    rank[3]++;
            }
          
            int sum = rank[0];
            int index = 0; 
            for(int i = 1;i < 4;i++)
            {
                if(rank[i] < sum)
                {
                    sum = rank[i];
                    index = i;
                }
            }
            if(i) printf(" ");            
            printf("%d:%d",sum+1,index+1); /* 某国的排名  */            
        }
        printf("
    ");
    }

    7-15 寻找大富翁

    胡润研究院的调查显示,截至2017年底,中国个人资产超过1亿元的高净值人群达15万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。

    输入格式:

    输入首先给出两个正整数N(≤106)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。

    输出格式:

    在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。

    输入样例:

    8 3
    8 12 7 3 20 9 5 18

    输出样例:

    20 18 12
     1 #include <stdio.h>
     2 
     3 #define N 1000000
     4 int key[N] = {0};
     5 
     6 int main()
     7 {
     8     int n,m,x,count=0,flag=0;
     9     scanf("%d%d",&n,&m); 
    10     for(int i=0; i<n; ++i){
    11         scanf("%d",&x);
    12         key[x]++;
    13     }
    14     for(int j=N-1; j>=0 && count<m; --j){
    15         if(key[j]){
    16             if(flag) printf(" ");
    17             printf("%d",j);
    18             flag = 1;
    19             count++;
    20             if(key[j]>1){
    21                 key[j]--;
    22                 j++;
    23             }
    24         }        
    25     }
    26 }
  • 相关阅读:
    从零基础到精通的前端学习路线
    js点击弹出网页弹框
    JS实现在线统计一个页面内鼠标点击次数-刷新过后也会保留上次点击次数
    Input文本框随着输入内容多少自动延伸有-bug
    关于Java 后台分页
    关于ECMAScript6 的学习01-ES6 的六种变量声明方式===关于常量const
    关于ECMAScript6 的学习01-ES6 的六种变量声明方式===关于块级变量 let
    接上篇 checkbox数据的带入
    关于checkbox 样式的改变 设置自定义样式
    关于文件上传-图片上传
  • 原文地址:https://www.cnblogs.com/GoldenEllipsis/p/10296011.html
Copyright © 2011-2022 走看看