首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用下标对数组进行排序而不移动数组元素

使用下标对数组进行排序而不移动数组元素
EN

Stack Overflow用户
提问于 2017-06-13 15:21:32
回答 2查看 798关注 0票数 1

我必须使用C中的mergesort对一个非负ints数组进行排序,但是有一个陷阱--我不能在实际的数组元素周围移动,比如如果我有{3,5,6,7,0,4,1,2},那么所需的输出应该是

第一个元素位于下标:4。

0 3 5

1 5 2

2 6 3

3 7 -1

4 0 6

5 4 1

6 1 7

7 2 0

查看原始输入的顺序如何保持不变,但只有键在比较数字时才被交换?到目前为止,我的主要职能是:

代码语言:javascript
复制
void Merge(int *A,int *L,int leftCount,int *R,int rightCount) 

{

    int i,j,k;

    // i - to mark the index of left sub-array (L)
    // j - to mark the index of right sub-array (R)
    // k - to mark the index of merged sub-array (A)
    i = 0; j = 0; k =0;

    while(i<leftCount && j< rightCount)
    {
        if(L[i]  <=  R[j])
        {
            //something important;
             i++;
        }
        else
        {
            //something important;
            j++;
        }
    }

    i=0;
    j=0;
    while(i < leftCount) A[k++] = L[i++]; //merge all input sequences without swapping initial order

    while(j < rightCount) A[k++] = R[j++];

}

// Recursive function to sort an array of integers.
void MergeSort(int *A,int n) 

{

    int mid,i,k, *L, *R;

    if(n < 2)
    {
       return; 
    }


    mid = n/2;  // find the mid index.

    // create left and right subarrays
    // mid elements (from index 0 till mid-1) should be part of left sub-array
    // and (n-mid) elements (from mid to n-1) will be part of right sub-array
    L = (int*)malloc(mid*sizeof(int));
    R = (int*)malloc((n- mid)*sizeof(int));

    for(i = 0;i<mid;i++) L[i] = A[i]; // creating left subarray
    for(i = mid;i<n;i++) R[i-mid] = A[i]; // creating right subarray

    MergeSort(L,mid);  // sorting the left subarray
    MergeSort(R,n-mid);  // sorting the right subarray
    Merge(A,L,mid,R,n-mid);  // Merging L and R into A as sorted list.
        free(L);
        free(R);
}

我知道,当合并排序过程中只有单个元素时,必须将递归树底部的所有元素的索引初始化为-1。然后,在比较左数组和右数组的数组元素时,我必须相应地更改这些索引。但那是我卡住的地方。我的教授告诉全班要使用链接列表,但我很难想象如何实现链接列表来实现这种索引。我不想让别人做我的家庭作业,我只想让别人用伪代码来解释我该怎么做,然后我就可以自己写实际的代码了。但是我太迷茫了,如果这个问题问得很糟糕,我很抱歉,但是我在这里打了一个新的屁股,我吓坏了。

EN

回答 2

Stack Overflow用户

发布于 2017-06-13 16:00:43

创建一个链接的项列表,其中每个列表项都具有每个数组项的值和索引。因此,除了prev/next之外,链接列表中的每个项都是一个具有struct成员uint value;uint index;的结构。

仅通过迭代数组和每个数组元素,预先填充链接列表,并在每个链接列表项中添加一个新的链接列表项,并在每个链接列表项中设置数组元素的值和索引。

使用预填充的链接列表作为实际数组值的“代理”,并对链接列表进行排序,就好像它是原始数组一样。也就是说,不是基于myArray[i]的排序,而是基于currentLinkListItem.value的排序。

票数 0
EN

Stack Overflow用户

发布于 2017-06-13 17:02:01

说到相互关联的清单:

代码语言:javascript
复制
typedef struct ValueNode
{
    struct ValueNode* next;
    int* value;
} ValueNode;

typedef struct ListNode
{
    struct ListNode* next;
    ValueNode* value;
} ListNode;

单链表就足够了..。

首先是合并算法:

代码语言:javascript
复制
ValueNode* merge(ValueNode* x, ValueNode* y)
{
    // just assuming both are != NULL...
    ValueNode dummy;
    ValueNode* xy = &dummy;
    while(x && y)
    {
        ValueNode** min = *x->value < *y->value ? &x : &y;
        xy->next = *min;
        *min = (*min)->next;
        xy = xy->next;
    }
    // just append the rest of the lists - if any...
    if(x)
    {
        xy->next = x;
    }
    else if(y)
    {
        xy->next = y;
    }
    return dummy.next;
}

假人只是因为不必在循环中检查for NULL .

现在让我们使用它:

代码语言:javascript
复制
int array[] = { 3, 5, 6, 7, 0, 4, 1, 2 };
ListNode head;
ListNode* tmp = &head;
for(unsigned int i = 0; i < sizeof(array)/sizeof(*array); ++i)
{
    // skipping the normally obligatory tests for result being 0...
    ValueNode* node = (ValueNode*) malloc(sizeof(ValueNode));
    node->value = array + i;
    node->next = NULL;
    tmp->next = (ListNode*) malloc(sizeof(ListNode));
    tmp = tmp->next;
    tmp->value = node;
}
tmp->next = NULL;

现在我们已经设置了一个列表,每个列表都包含一个元素。现在,我们对两个后续列表进行合并。我们需要注意:如果我们将两个列表合并为一个,保持它作为新的头,将下一个列表合并到其中,等等,那么我们就实现了选择排序!因此,我们需要确保在所有其他数组被合并之前,我们没有接触到已经合并的数组。所以下一步看起来有点复杂..。

代码语言:javascript
复制
while(head.next->next) // more than one single list element?
{
    tmp = head.next;
    while(tmp)
    {
        ListNode* next = tmp->next;
        if(next)
        {
            // we keep the merged list in the current node:
            tmp->value = merge(tmp->value, next->value);
            // and remove the subsequent node from it:
            tmp->next = next->next;
            free(next);
        }
        // this is the important step:
        // tmp contains an already merged list
        // -> we need to go on with the NEXT pair!
        tmp = tmp->next;
        // additionally, if we have an odd number of lists,
        // thus at the end no next any more, we set tmp to NULL,
        // too, so we will leave the loop in both cases...
    }
}

最后,我们可以打印结果;请注意,在您的外部链接列表中只剩下一个链接列表:

代码语言:javascript
复制
ValueNode* temp = head.next->value;
while(temp)
{
    printf("%d\n", *temp->value);
    temp = temp->next;
}

现在还缺的是释放分配的内存-我会留给你的.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44525606

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档