【问题标题】:Rearranging an array with respect to another array相对于另一个数组重新排列一个数组
【发布时间】:2016-06-20 11:20:43
【问题描述】:

我有 2 个数组,并行:

defenders = {1,5,7,9,12,18};
attackers = {3,10,14,15,17,18};

两者都已排序,我要做的是重新排列防守数组的值,以便他们赢得更多比赛(防守者 [i] > 攻击者 [i]),但我在如何交换防守者中的值时遇到问题大批。所以实际上我们只使用防御者数组来处理攻击者。

我有这个,但如果有什么变化的话,我很确定我做得不对。它应该是一种蛮力方法。

void rearrange(int* attackers, int* defenders, int size){
int i, c, j;
int temp;

for(i = 0; i<size; i++){
  c = 0;
  j = 0;
  if(defenders[c]<attackers[j]){
            temp = defenders[c+1];
            defenders[c+1] = defenders[c];
            defenders[c] = temp;
            c++;
            j++;
     }
    else
        c++;
        j++;

   }
}

编辑:我之前确实问过这个问题,但我觉得我的措辞很糟糕,并且不知道如何“撞击”旧帖子。

【问题讨论】:

  • 你在每个循环的开始初始化cj。好吗?
  • 注意:注意不要造成超出范围的访问。
  • @MikeCAT 我这样做是为了让 c 和 j 不会变成巨大的数字。我也有一个 if 语句来限制 c+1,但它没有做太多。
  • @gsamaras 是的,我编辑了我的帖子以包含我的解释

标签: c arrays loops sorting brute-force


【解决方案1】:

说实话,我没有看你的代码,因为我必须在不到 2.30 小时内醒来上班,希望你不会对我有不好的感觉.. :)


我实现了 Eugene Sh 提出的algorithm。在深入研究代码之前,您可能需要先阅读一些链接:

  1. qsort in C
  2. qsort and structs
  3. shortcircuiting

我的做法:

  1. 通过扫描attdef 创建合并数组。
  2. 对合并数组进行排序。

  3. 用满足 ad 模式的值重新填充def

  4. 用剩余的值(即 失败)*.

*在我的方法中,第 3 步和第 4 步需要两次通过,也许它会变得更好。

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  char c; // a for att and d for def
  int v;
} pair;

void print(pair* array, int N);
void print_int_array(int* array, int N);
// function to be used by qsort()
int compar(const void* a, const void* b) {
    pair *pair_a = (pair *)a;
    pair *pair_b = (pair *)b;
    if(pair_a->v == pair_b->v)
        return pair_b->c - pair_a->c; // d has highest priority
    return pair_a->v - pair_b->v;
}

int main(void) {
    const int N = 6;
    int def[] = {1, 5, 7, 9, 12, 18};
    int att[] = {3, 10, 14, 15, 17, 18};
    int i, j = 0;
    // let's construct the merged array
    pair merged_ar[2*N];
    // scan the def array
    for(i = 0; i < N; ++i) {
        merged_ar[i].c = 'd';
        merged_ar[i].v = def[i];
    }
    // scan the att array
    for(i = N; i < 2 * N; ++i) {
        merged_ar[i].c = 'a';
        merged_ar[i].v = att[j++]; // watch out for the pointers
        // 'merged_ar' is bigger than 'att'
    }
    // sort the merged array
    qsort(merged_ar, 2 * N, sizeof(pair), compar);
    print(merged_ar, 2 * N);
    // scan the merged array
    // to collect the patterns
    j = 0;
    // first pass to collect the patterns ad
    for(i = 0; i < 2 * N; ++i) {
        // if pattern found
        if(merged_ar[i].c == 'a' &&     // first letter of pattern
           i < 2 * N - 1         &&     // check that I am not the last element
           merged_ar[i + 1].c == 'd') {     // second letter of the pattern
            def[j++] = merged_ar[i + 1].v;  // fill-in `def` array
            merged_ar[i + 1].c = 'u';   // mark that value as used
        }
    }
    // second pass to collect the cases were 'def' loses
    for(i = 0; i < 2 * N; ++i) {
        // 'a' is for the 'att' and 'u' is already in 'def'
        if(merged_ar[i].c == 'd') {
            def[j++] = merged_ar[i].v;
        }
    }
    print_int_array(def, N);
    return 0;
}

void print_int_array(int* array, int N) {
    int i;
    for(i = 0; i < N; ++i) {
        printf("%d ", array[i]);
    }
    printf("\n");
}

void print(pair* array, int N) {
    int i;
    for(i = 0; i < N; ++i) {
                printf("%c %d\n", array[i].c, array[i].v);
        }
}

输出:

gsamaras@gsamaras:~$ gcc -Wall px.c
gsamaras@gsamaras:~$ ./a.out 
d 1
a 3
d 5
d 7
d 9
a 10
d 12
a 14
a 15
a 17
d 18
a 18
5 12 18 1 7 9

【讨论】:

  • 现在我觉得我应该添加我的整个代码,我有点不确定如何添加它,但我将值扫描到我的 2 个动态分配的数组(防御者/攻击者)中。然后我在两个数组上调用了mergesort。这就是我在原始问题中获得最终结果数组的方式。我不确定我可以多么容易地使用结构,但我可以尝试
  • 好吧,我现在正在研究我的方法@Jude,效果很好。希望能帮助到你。 :D 你可以重新思考为什么你的方法一开始就不起作用。另外,很好的问题,+1。
  • @Jude 为什么不使用结构?因为您的数组是动态分配的?使用数组时没有区别(如果它们是动态分配的!!)。
  • 真的吗?我没有看到任何提到@TomKarzes 的地方。即使是这样,我希望他真的研究我的答案并学习!无论如何感谢您的投票。 :)
  • 嗯,它是重复的(应该这样关闭)。在此之前还有另外两个相同的帖子。所以,是的,家庭作业。
【解决方案2】:

问题是您在循环的每次迭代中将 c 和 j 重置为零。因此,您只需要比较每个数组中的第一个值。

另一个问题是,如果防御者数组的最后一个值小于攻击者数组的最后一个值,您将读取防御者数组的末尾。

另一个问题或者可能只是奇怪的是,您在 if 语句的两个分支中都增加了 c 和 j。如果这是你真正想要的,那么 c 和 j 没用,你可以使用 i。

我会为您提供一些更新的代码,但是对于您要实现的目标没有足够好的描述;我只能指出明显的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 2016-06-18
    • 2019-05-02
    • 1970-01-01
    • 2012-02-14
    • 2015-04-03
    相关资源
    最近更新 更多