【问题标题】:Trouble with qsort with key/value structs in a btreebtree 中带有键/值结构的 qsort 问题
【发布时间】:2021-08-21 19:55:18
【问题描述】:

我正在尝试对数组中的 key/val 结构进行排序,它是 b 树的树节点。当我将 key/val 结构插入节点时,我将其放在结构的末尾,然后执行 qsort。

struct kv 
{
   char *key;   //This is the key
   int  lba;    //The value of the key
   unsigned char size;   //Size of key for memcmp.
};

struct tnode 
{
    unsigned char nkeys;
    unsigned char keysize;                   
    kv *items[205];
...
};

int compare_key(const void *a,const void *b)
{
    const kv *A = (const kv *) a;
    const kv *B = (const kv *) b;

    print_kv(A);
    print_kv(B);

    //Why return thesee? It's the right most element ergo it's pointing to it's parent's block.
    if (A->key == NULL)
        return INT_MAX;
    else if (B->key == NULL)
        return INT_MIN;
    else
        return memcmp(A->key,B->key,A->size);
}
void print_node(tnode *node)
{
    //Useful for debugging
    int i;
    printf("\nThis Nodes LBA is:%d\nNumber of Keys in node:%x\n",node->lba,node->nkeys);
    for (i = 0; i <= node->nkeys; ++i)
        print_kv(node->items[i]);
    printf("\n");

}

void print_kv(const kv *item)
{
    if (item->key == NULL)
        printf("\nNULL Key who's lba is: %d\n",item->lba);
    else
        printf("\nAddress:%p\nKey:%s\nLBA:%d\nSize:%d\n",item,item->key,item->lba,item->size);
}

unsigned int tnode_insert(tnode *node, kv *item)
{
    //Insert key & val in node
    node->items[++node->nkeys] = item;

    print_node(node);

    printf("Started sorting\n");
    qsort(node->items,node->nkeys,sizeof(kv),compare_key);


    print_node(node);

    return item->lba;
}

这会输出什么:

This Nodes LBA is:1
Number of Keys in node:4

Address:0x19c6a00
Key:Alexis
LBA:4
Size:200

Address:0x19c6a20
Key:Allison
LBA:11
Size:200

Address:0x19c6a40
Key:Caleb
LBA:10
Size:200

Address:0x19c6a60
Key:Daniel
LBA:2
Size:200

NULL Key who's lba is: 6

Started sorting

Address:0x19c6380
Key:?j?
LBA:27028000
Size:0

Address:0x19c6390
Key:`l?
LBA:27028064
Size:0

NULL Key who's lba is: 0

NULL Key who's lba is: 0

Address:0x19c63a0
Key:
LBA:27024960
Size:0

NULL Key who's lba is: 0

Address:0x19c6380
Key:?j?
LBA:27028000
Size:0

Address:0x19c63a0
Key:
LBA:27024960
Size:0

Address:0x19c6390
Key:`l?
LBA:27028064
Size:0

Address:0x19c63a0
Key:
LBA:27024960
Size:0

This Nodes LBA is:1
Number of Keys in node:5

Address:0x19c6a00
Key:Alexis
LBA:4
Size:200

Address:0x19c6a20
Key:Allison
LBA:11
Size:200

Address:0x19c6a40
Key:Caleb
LBA:10
Size:200

Address:0x19c6a60
Key:Daniel
LBA:2
Size:200

NULL Key who's lba is: 6

Address:0x19c5e40
Key:Bob
LBA:12
Size:200

Insert return value: 12

我收集到的是我使用快速排序所做的事情是不正确的,但我不知道那是什么。我试图遵循 gnu 许可证,但我很难过。也许比较函数假设所有结构都是连续的?非常感谢您的帮助。

更新: 改成 sizeof(kv*)

This Nodes LBA is:1
Number of Keys in node:4

Address:0x1dc3a00
Key:Alexis
LBA:4
Size:200

Address:0x1dc3a20
Key:Allison
LBA:11
Size:200

Address:0x1dc3a40
Key:Caleb
LBA:10
Size:200

Address:0x1dc3a60
Key:Daniel
LBA:2
Size:200

NULL Key who's lba is: 6

Started sorting from:0x1dc3380
*(const kv **) a:0x1dc3a00
Address:0x1dc3380
Key:?:?
LBA:31210016
Size:0

Address:0x1dc3388
Key:?;?
LBA:31210048
Size:0

Address:0x1dc3398
Key:0=?
LBA:31210112
Size:0

Address:0x1dc33a0
Key:
LBA:31206976
Size:0

Address:0x1dc3390
Key:`<?
LBA:31210080
Size:0

Address:0x1dc3398
Key:0=?
LBA:31210112
Size:0

Address:0x1dc3380
Key:?:?
LBA:31210016
Size:0

Address:0x1dc3390
Key:`<?
LBA:31210080
Size:0

Address:0x1dc3388
Key:?;?
LBA:31210048
Size:0

Address:0x1dc3390
Key:`<?
LBA:31210080
Size:0

This Nodes LBA is:1
Number of Keys in node:5

Address:0x1dc3a00
Key:Alexis
LBA:4
Size:200

Address:0x1dc3a20
Key:Allison
LBA:11
Size:200

Address:0x1dc3a40
Key:Caleb
LBA:10
Size:200

Address:0x1dc3a60
Key:Daniel
LBA:2
Size:200

NULL Key who's lba is: 6

Address:0x1dc2e40
Key:Bob
LBA:12
Size:200

Insert return value: 12
Reads: 3
Writes: 1

【问题讨论】:

  • 你知道快速排序在几乎排序的列表上表现最差吗?如果您关心性能,那么最好在正确的位置插入。
  • 我只是在寻找可靠正确的快速而肮脏的排序。
  • @stark qsort 不一定是快速排序。 stackoverflow.com/questions/13353904/…
  • sizeof(kv) 应该是sizeof(kv*)?你有一个items 的指针数组。更好的sizeof *node-&gt;items,如果您使用取消引用的指针,您将永远不会弄错类型大小。

标签: c


【解决方案1】:
  1. 比较函数将地址传递给元素。您对指针数组进行排序。所以比较函数接收一个指向数组中指针的指针。做:

    int compare_key(const void *a,const void *b)
    {
        const kv *A = *(const kv *const *)a;
        const kv *B = *(const kv *const *)b;
    
  2. 您有一个指针数组,并且您正在对指针进行排序,而不是 kv 结构。您必须传递一个指针作为元素的大小。

    qsort(node->items, node->nkeys, sizeof(kv*), compare_key);
    

【讨论】:

  • 谢谢!我在两种情况下都使用了比较函数,但不同的数据结构在我更改代码时会导致段错误。我现在为键做了两个比较功能。再次感谢
猜你喜欢
  • 1970-01-01
  • 2011-12-14
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
相关资源
最近更新 更多