【问题标题】:Double sort (Sort elements on 2 different values)双重排序(对 2 个不同值的元素进行排序)
【发布时间】:2013-11-19 04:27:15
【问题描述】:

假设我有一个结构 node,如下所示:

typedef struct node{
    int t;
    double p;
}node;

然后我还有一个struct node 数组,其中一些具有相等的值p

我想做的是:

首先,根据值p对元素进行排序。在我有一个基于 p 的排序数组之后,我希望每个具有相同 p 的子数组都根据值 t 进行排序。

例如:

如果我的原始数组看起来像这样(第一个元素是 p,第二个元素是 t):

[0,10|1], [0.05|0], [0,10|0], [0,05|2], [0,10|2], [0,15|1], [ 0,05|1]

双排后应该是这样的:

[0,05|0], [0,05|1], [0,05|2], [0,10|0], [0,10|1], [0,10|2] , [0,15|1]。

我已经提出了基于p 的冒泡排序,但是我在如何对t 上的子数组进行排序时遇到了困难。这是p上的冒泡排序代码。

node *sort_p(node *nodes, int num) {
    int i, j;
    node *temp = malloc(sizeof(node));

    for(i=1; i<num; i+=1){
        for(j=0; j<num-i; j+=1){
            if(nodes[j].p > nodes[j+1].p){
                *temp = nodes[j];
                nodes[j] = nodes[j+1];
                nodes[j+1] = *temp;
            }
        }
    }
    free(temp);

    return nodes;
}

我怎样才能完成所需的双重排序?

更新

我编写了一个可与 qsort() 一起使用的比较方法,如下所示,但它不会从某一点产生所需的结果。

我正在调用这样的方法:qsort(nodes, num_of_nodes, sizeof(node), compare_pairs);

compare_pairs() 看起来像这样:

static int compare_pairs(node *n1, node *n2){

const node *na1 = n1;
const node *na2 = n2;

if(na1->p< na2->p) return -1;
if(na1->p> na2->p) return 1;

if(na1->t < na2->t) return -1;
if(na1->t > na2->t) return 1;

return 0;

问题

不受欢迎的行为从 3 开始。 STEP 看起来像这样:

列表:[0.10 | 2] [0.10 | 999] [0.10 | 999] [0.15 | 999] [0.15 | 999] [0.15 | 1] [0.25 | 999]

应该是这样的:

列表:[0.10 | 2] [0.10 | 999] [0.10 | 999] [0.15 | 1] [0.15 | 999] [0.15 | 999] [0.25 | 999]

初始列表: [0.25 | 999] [0.15 | 999] [0.15 | 999] [0.10 | 999] [0.10 | 999] [0.05 | 999] [0.05| 999] [0.05 | 999] [0.05 | 999] [0.05 | 999]

  1. 步骤:

擦除(最小)节点 0.050000...

擦除(最小)节点 0.050000...

正在创建(新)节点 0.100000...

列表:[0.05 | 999] [0.05 | 999] [0.05 | 999] [0.10 | 1] [0.10 | 999] [0.10 | 999] [0.15 | 999] [0.15 | 999] [0.25 |第999章

  1. 步骤:

擦除(最小)节点 0.050000...

擦除(最小)节点 0.050000...

正在创建(新)节点 0.100000...

列表:[0.05 | 999] [0.10 | 1] [0.10 | 2] [0.10 | 999] [0.10 | 999] [0.15 | 999] [0.15 | 999] [0.25 |第999章

  1. 步骤:

擦除(最小)节点 0.050000...

擦除(最小)节点 0.100000...

正在创建(新)节点 0.150000...

列表:[0.10 | 2] [0.10 | 999] [0.10 | 999] [0.15 | 999] [0.15 | 999] [0.15 | 1] [0.25 |第999章

  1. 步骤:

擦除(最小)节点 0.100000...

擦除(最小)节点 0.100000...

正在擦除(新)节点 0.200000...

列表:[0.10 | 999] [0.15 | 999] [0.15 | 999] [0.15 | 1] [0.20 | 1] [0.25 |第999章

  1. 步骤:

擦除(最小)节点 0.100000...

擦除(最小)节点 0.150000...

正在创建(新)节点 0.250000...

列表:[0.15 | 999] [0.15 | 1] [0.20 | 1] [0.25 | 1] [0.25 |第999章

  1. 步骤:

擦除(最小)节点 0.150000...

擦除(最小)节点 0.150000...

正在擦除(新)节点 0.300000...

列表:[0.20 | 1] [0.25 | 1] [0.25 | 999] [0.30 | 1]

  1. 步骤:

擦除(最小)节点 0.200000...

擦除(最小)节点 0.250000...

正在擦除(新)节点 0.450000...

列表:[0.25 | 999] [0.30 | 1] [0.45 | 1]

  1. 步骤:

擦除(最小)节点 0.250000...

擦除(最小)节点 0.300000...

正在创建(新)节点 0.550000...

列表:[0.45 | 1] [0.55 | 1]

  1. 步骤:

擦除(最小)节点 0.450000...

擦除(最小)节点 0.550000...

正在创建(新)节点 1.000000...

列表:[1.00 | 1]

总体思路*

在每一步中,从列表中删除两个最小节点,并在列表中插入一个新节点。被插入的节点的 t 值比列表中的最大值大 1,但它不会将自身与 t 值 999 进行比较。如果列表中最大的有 t = 999,那么插入的将有 1。

找到最大的 t

int max_t(node *nodes, int num, double p){
int max_t= 0;
int i;
for(i=0; i<num; i+=1){
    if(nodes[i].p== p && nodes[i].t != 999){
        if(nodes[i].t > max_t){
            max_t = nodes[i].t;
        }
    }
}
return max_t;

主要代码:

node *nodes = malloc(num_of_nodes*sizeof(node));
int i;
for(i=0; i<num_of_nodes; i+=1){
    node n;
    n.t = 999;
    n.p = *(probabs+ i);
    *(nodes+i) = n;
}

qsort(nodes, num_of_nodes, sizeof(node), compare_pairs);

while(num_of_nodes> 1){

    printf("\n%d. STEP:\n", z);
    z += 1;

    // 2) Find two min nodes
    node *min_n1 = malloc(sizeof(node));
    node *min_n2 = malloc(sizeof(node));

    *min_n1 = nodes[0];
    printf("Erasing (min) node %lf...\n", min_n1->p);
    nodes= erase_node(nodes, min_n1, num_of_nodes);
    num_of_nodes -= 1;

    *min_n2 = nodes[0];
    printf("Erasing (min) node %lf...\n", min_n2->p);
    nodes= erase_node(nodes, min_n2, num_of_nodes);
    num_of_nodes-= 1;

    // 3) Create new node, add it to the list
    node *new:node = malloc(sizeof(node));
    new_node->p= min_n1->p + min_n2->p;
    double p = new->p;
    int max_t = max_t(nodes, num_of_nodes, p);
    new_node->t = max_t + 1;

    printf("Creating (new) node %lf...\n", new_node->p);
    node = add_node(nodes, new_node, num_of_nodes);
    num_of_nodes += 1;

    qsort(nodes, num_of_nodes, sizeof(node), compare_pairs);

    printf("List: ");
    int k;
    for(k=0; k<num_of_nodes; k+=1){
        printf("[%.2lf | %d]  ", nodes[k].p, nodes[k].t);
    }
    printf("\n");

【问题讨论】:

  • 请检查更新!

标签: c arrays sorting


【解决方案1】:

你的方法是不必要的复杂。无需“两次排序”,只需增强比较运算符即可。

另外,在 C 中使用qsort() 对数组进行排序,这比滚动自己的排序要容易得多,而且性能也可能更好。

基本上,您应该尝试像这样填充函数的空白:

static int compare_pairs(const void *a, const void *b)
{
  const node *na = a, *nb = b;

  /* more code here */
}

当你说“我希望每个具有相同 p 的子数组都根据值 t 进行排序”时,基本上你就有了解决方案。

这意味着比较函数的主体变为:

if(na->p < nb->p)
  return -1;
if(na->p > nb->p)
  return 1;
/* If we get this far, we know the p values are equal, so tie-break with t. */
if(na->t < nb->t)
  return -1;
if(na->t > nb->t)
  return 1;
return 0;

最后,please don't cast the return value of malloc() in C

【讨论】:

    猜你喜欢
    • 2012-04-15
    • 1970-01-01
    • 2012-10-16
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    相关资源
    最近更新 更多