英文:
How to "sort and modify" a list?
问题
我不确定这个主题是否已经被讨论过,但如果是这样,我没有正确的关键词来找到它。在我的代码中,我提取一个映射,就像这样:{5,0,23,2,2,0}
。如你所见,这些值不是连续的。我想要做的是将这个映射转换为返回的列表是{3,0,4,1,2,0}
。这里的0
表示元素应该被忽略。所以基本上我想做的是根据它们的顺序重新编号这些元素,而不是移动它们在列表中的位置。
我通过首先创建我的初始数组的副本,然后使用stdlib C库中的qsort
对这个副本进行排序来实现这个目标。我还创建了一个return_list
,其中将存储我的最终映射。
(初始数组是vec
)
elt_count = 1;
for (size_t i = 0; i < n; i++) {
if (copy[i] != 0) {
for (size_t j = 0; j < n; j++) {
if (copy[i] == vec[j]) {
return_list[j] = elt_count;
vec[j] = 0;
elt_count++;
break;
}
}
}
}
在这里,我使用一个计数器为最终映射赋予它的值。
问题是,我的方法中的这部分需要很多时间,而且减慢了我的整个程序,而我本应该使用映射来节省时间。
我认为我可以像这样存储每个元素的位置来尝试提高性能:
vec = (5,0,23,2,2,0)
5: (0)
23: (2)
2: (3,4)
然而,我不确定如何实施这个并且如何使用它来提高性能。
当然,欢迎任何其他改进性能的想法!
英文:
I am not sure if this subject was already treated but if it's the case I did not have the right keyword to find it.
In my code I extract a mapping so let's say: {5,0,23,2,2,0}
. As you can see the values are not contiguous. What I would like to do is transform this mapping so that the returned list is {3,0,4,1,2,0}
. Here 0
means that the element should be ignored. So basically what I want to do is renumber the elements based on their order without moving them in the list.
I did that by first creating a copy of my initial array and then sorting this copy using qsort
from the stdlib C library. I also created a return_list
in which my final mapping will be stored.
(the initial array is vec
)
elt_count = 1;
for (size_t i = 0; i < n; i++) {
if (copy[i] != 0) {
for (size_t j = 0; j < n; j++) {
if (copy[i] == vec[j]) {
return_list[j] = elt_count;
vec[j] = 0;
elt_count++;
break;
}
}
}
}
Here I use a counter to give the final mapping its values.
The problem is that this part of my method takes a lot of time and slows down my whole program while I was supposed to use the mapping to gain time.
I think I could store the position of each elements like this to try and improve the performances:
vec = (5,0,23,2,2,0)
5: (0)
23: (2)
2: (3,4)
However I am not sure how to implement this and then use it to gain performance.
Of course any other ideas to improve the performances are welcome !
答案1
得分: 2
以下是您要翻译的内容:
一种简单的方法是创建一个包含值的索引的数组副本:
int a2[n][2];
int zeros = 0;
for (int i = 0; i < n; i++) {
a2[i - zeros][0] = vec[i];
a2[i - zeros][1] = i;
zeros += (vec[i] == 0);
}
现在 `a2` 是一个长度为 `n-zeros` 的数组,其条目是 `vec` 的非零元素与它们的索引配对。
现在对 `a2` 进行排序:
qsort(a2, n - zeros, sizeof(a2[0]), cmp_a2);
使用这个比较函数:
int cmp_a2(const void *v, const void *w) {
const int *a = v;
const int *b = w;
if (a[0] < b[0]) return -1;
if (a[0] > b[0]) return 1;
if (a[1] < b[1]) return -1;
if (a[1] > b[1]) return 1;
return 0;
}
现在,您可以使用排序后的 `a2` 中存储的原始索引替换数组中的原始元素:
for (int i = 0; i < n - zeros; i++) {
vec[a2[i][1]] = i + 1;
}
这里是所有部分完整的工作示例:
#include <stdlib.h>
#include <stdio.h>
void print_array(int *a, size_t n) {
for (int i = 0; i < n; i++)
printf("%s%d", i > 0 ? ", " : "", a[i]);
printf("\n");
}
int cmp_a2(const void *v, const void *w) {
const int *a = v;
const int *b = w;
if (a[0] < b[0]) return -1;
if (a[0] > b[0]) return 1;
if (a[1] < b[1]) return -1;
if (a[1] > b[1]) return 1;
return 0;
}
void order_array(int *vec, size_t n) {
int (*a2)[2] = malloc(n * 2 * sizeof(int));
size_t zeros = 0;
for (int i = 0; i < n; i++) {
a2[i - zeros][0] = vec[i];
a2[i - zeros][1] = i;
zeros += (vec[i] == 0);
}
qsort(a2, n - zeros, sizeof(a2[0]), cmp_a2);
for (int i = 0; i < n - zeros; i++) {
vec[a2[i][1]] = i + 1;
}
free(a2);
}
int main(int argc, char *argv[]) {
int a[] = {5,0,23,2,2,0};
size_t n = sizeof(a) / sizeof(*a);
print_array(a, n);
order_array(a, n);
print_array(a, n);
}
请注意,这段代码将数组 a
中的元素重新排序,将非零元素替换为它们在重新排序后的数组中的索引。
英文:
One easy approach is to make a copy of your array including the indexes of the values:
int a2[n][2];
int zeros = 0;
for (int i = 0; i < n; i++) {
a2[i - zeros][0] = vec[i];
a2[i - zeros][1] = i;
zeros += (vec[i] == 0);
}
Now a2
is an array of length n-zeros
, and its entries are the non-zero elements of vec
paired with their indexes.
Now sort a2
:
qsort(a2, n - zeros, sizeof(a2[0]), cmp_a2);
Using this comparison function:
int cmp_a2(const void *v, const void*w) {
const int *a = v;
const int *b = w;
if (a[0] < b[0]) return -1;
if (a[0] > b[0]) return 1;
if (a[1] < b[1]) return -1;
if (a[1] > b[1]) return 1;
return 0;
}
Now you can replace the original elements in the array, using the original indices stored in the sorted a2
:
for (int i = 0; i < n - zeros; i++) {
vec[a2[i][1]] = i + 1;
}
Here's all the pieces together as complete working example:
#include <stdlib.h>
#include <stdio.h>
void print_array(int *a, size_t n) {
for (int i = 0; i < n; i++)
printf("%s%d", i>0 ? ", " : "", a[i]);
printf("\n");
}
int cmp_a2(const void *v, const void*w) {
const int *a = v;
const int *b = w;
if (a[0] < b[0]) return -1;
if (a[0] > b[0]) return 1;
if (a[1] < b[1]) return -1;
if (a[1] > b[1]) return 1;
return 0;
}
void order_array(int *vec, size_t n) {
int (*a2)[2] = malloc(n * 2 * sizeof(int));
size_t zeros = 0;
for (int i = 0; i < n; i++) {
a2[i - zeros][0] = vec[i];
a2[i - zeros][1] = i;
zeros += (vec[i] == 0);
}
qsort(a2, n - zeros, sizeof(a2[0]), cmp_a2);
for (int i = 0; i < n - zeros; i++) {
vec[a2[i][1]] = i + 1;
}
free(a2);
}
int main(int argc, char *argv[]) {
int a[] = {5,0,23,2,2,0};
size_t n = sizeof(a) / sizeof(*a);
print_array(a, n);
order_array(a, n);
print_array(a, n);
}
答案2
得分: -1
你可以使用标准库函数 qsort 和 bsearch 来解决这个问题。以下是一个开始:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])
int ElemDiff(const void *leftElemPtr, const void *rightElemPtr) {
return *(int *) leftElemPtr - *(int *) rightElemPtr;
}
int main(void)
{
int vec[] = {5, 0, 23, 2, 2, 0};
int sortedVec[LEN(vec)];
int i, *tail;
memcpy(sortedVec, vec, sizeof (vec));
qsort(sortedVec, LEN(sortedVec), sizeof sortedVec[0], ElemDiff);
for (i = 0; i < LEN(vec); i++) {
tail = bsearch(vec + i, sortedVec, LEN(sortedVec), sizeof sortedVec[0], ElemDiff);
assert(tail != NULL);
printf("%lld ", tail - sortedVec);
}
putchar('\n');
return 0;
}
这会打印:
4 0 5 2 2 0
英文:
You can use the the standard library functions qsort and bsearch to solve the problem. Here is a start:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])
int ElemDiff(const void *leftElemPtr, const void *rightElemPtr) {
return *(int *) leftElemPtr - *(int *) rightElemPtr;
}
int main(void)
{
int vec[] = {5, 0, 23, 2, 2, 0};
int sortedVec[LEN(vec)];
int i, *tail;
memcpy(sortedVec, vec, sizeof (vec));
qsort(sortedVec, LEN(sortedVec), sizeof sortedVec[0], ElemDiff);
for (i = 0; i < LEN(vec); i++) {
tail = bsearch(vec + i, sortedVec, LEN(sortedVec), sizeof sortedVec[0], ElemDiff);
assert(tail != NULL);
printf("%lld ", tail - sortedVec);
}
putchar('\n');
return 0;
}
This will print
4 0 5 2 2 0
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论