我试图找出(使用快速排序算法)如何通过2个标准对结构数组进行排序。例如,假设我有一个结构:
struct employee{
char gender[12];
char name[12];
int id;
};
说我的输入是:
struct employee arr[3]=
{
{"male","Matt",1234},
{"female","Jessica",2345},
{"male","Josh",1235}
};
我想首先按性别对元素进行排序,然后按升序排列ID。一个例子是,所有的男性首先打印出他们的ID,然后是所有的女性。我试图这样做而不使用qsort函数,但我没有丝毫想知道如何检查。这是我的排序功能:
void quicksort(struct employee *arr, int left, int right)
{
int pivot, l, r, temp;
if(left < right)
{
p = left;
l = left;
r = right;
while(l < r)
{
while(arr[l].id <= arr[p].id && l <= right)
l++;
while(arr[r].id > arr[p].id && r >= left)
r--;
if(l < r)
{
temp = arr[l].id;
arr[l].id = arr[r].id;
arr[r].id = temp;
}
}
temp = arr[r].id;
arr[r].id = arr[p].id;
arr[p].id = temp;
quicksort(arr, left, r-1);
quicksort(arr, r+1, right);
}
}
有什么建议吗?我以为我可以使用strcmp,但我无法弄清楚在函数中包含它的位置。
答案 0 :(得分:5)
你当然可以内联比较函数,以及交换器。下面的代码是非常基本的,依赖于有效的指针,但你会明白这一点。我也冒昧地削减你的快速排序,修复一路上的事情(我希望)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// employee record
struct employee
{
char gender[12];
char name[12];
int id;
};
// swap employee records
void swap_employee(struct employee *left, struct employee *right)
{
struct employee tmp = *right;
*right = *left;
*left = tmp;
}
// compare employee records
int compare_employee(const struct employee* left,
const struct employee* right)
{
int gender = strcmp(left->gender, right->gender);
return (gender ? gender : (left->id - right->id));
}
// quicksort for employees
static void quicksort_(struct employee *arr, int left, int right)
{
struct employee p = arr[(left+right)/2]; // as good as any
int l = left, r = right; // movable indicies
while (l <= r)
{
while (compare_employee(arr+l, &p) < 0)
++l;
while (compare_employee(arr+r, &p) > 0)
--r;
if (l <= r)
{
swap_employee(arr+l, arr+r);
++l; --r;
}
}
if (left < r)
quicksort_(arr, left, r);
if (l < right)
quicksort_(arr, l, right);
}
// exposed API
void quicksort(struct employee *arr, int count)
{
if (arr && (count>0))
quicksort_(arr, 0, count-1);
}
/* sample usage */
int main(int argc, char *argv[])
{
struct employee arr[]=
{
{"male","Matt",1234},
{"female","Jessica",2345},
{"male","Josh",1235},
{"female","Betsy",2344},
{"male","Roger",1233}
};
quicksort(arr, sizeof(arr)/sizeof(arr[0]));
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);++i)
printf("%s, %s, %d\n", arr[i].gender,arr[i].name, arr[i].id);
return EXIT_SUCCESS;
}
<强>结果
female, Betsy, 2344
female, Jessica, 2345
male, Roger, 1233
male, Matt, 1234
male, Josh, 1235
答案 1 :(得分:1)
这并不难。您只需要一个函数(或代码块,看到您希望它“硬编码”)来比较您的结构。在您给出的示例代码中,您使用arr[l].id <= arr[p].id
比较当前对象。那就是你只考虑id来找出你的元素适合的位置。您只需要在此时使用其他字段进行比较。一个函数会更加整洁(我在你之前的问题中给了你这样一个函数)。
您也只是在交换时移动id字段 - 在数据项中保持名称和性别不变。你应该移动整个结构。
答案 2 :(得分:0)
只需使用内置的qsort
,并传递比较器函数,该函数首先比较性别,并仅在第一次比较中出现“关系”时查询ID号。
答案 3 :(得分:0)
我认为你应该按性别排序你的阵列,一个是男性,一个是女性。然后使用quicksort函数在这两个数组中进行排序。
您可以使用strcmp将原始数组排序为两个数组:一个用于男性,一个用于女性。
答案 4 :(得分:0)
int compare_employee (struct employee * a, struct employee * b) {
int diff = strcmp(a->gender, b->gender);
if (diff) // if gender different
return -diff; // sort descending, please double check this and reverse in case I am wrong
return a->id - b->id; // else sort by id
}
如果a < b
将输出负数,如果a > b
则输出正数,如果相等则输出零。
在您自己的快速排序或qsort
比较器中使用它。