C最好的函数是在元素上得到分割数组,等于和大于某个值

时间:2016-01-22 16:04:34

标签: c algorithm function

我在C编程。在少于,等于和大于某个值x的元素上吐出数组的最佳方法(我的意思是线性时间)是什么。

例如,如果我有数组

{1, 4, 6, 7, 13, 1, 7, 3, 5, 11}

x = 7那么它应该是

{1, 4, 6, 1, 3, 5, 7, 7, 13, 11 } 

我不想对元素进行排序,因为我需要更有效的方法。当然,在此示例中,可以是{1, 4, 6, 1, 3, 5}{13, 11}的任何排列。

我的理解:比数组中的某些元素更少或更大......在这个例子中它是7。

我的功能是:

int x = 7;
int u =0, z = 0;
for(int i=0; i<size-1; i++)  // size - 1 because the last element will be choosen value
{
  if(A[i] == x)
    swap(A[i], A[u]);
  else if(A[i] == x)
  {
     swap(A[i], A[n-(++z)]);
     continue;
  }
  i++
 }

for(int i = 0; i<z; i++)
   swap(A[u+i],A[size-(++z)];

其中u是当前较少元素的数量,z是等于元素的数量

但是如果我有数组中的每个元素等于那里它不起作用(大小 - (++ z))是低于0

4 个答案:

答案 0 :(得分:4)

这是所谓的Dutch national flag problem,以三条条纹的荷兰国旗命名。 (由荷兰人EW Dijkstra命名。)它类似于实现快速排序所需的partition函数,但在快速排序的大多数解释中,提出了一种双向分区算法,而在这里我们正在寻找一个三分区。经典的快速分配算法将矢量分为两部分,一部分由不大于枢轴的元素组成,另一部分由严格更大的元素组成。 [见注1]

维基百科文章为Dijkstra的解决方案提供了伪代码,该解决方案(与通常在快速排序的讨论中提出的经典分区算法不同)从向左移动到向量:

void dutchflag(int* v, size_t n, int x) {
  for (size_t lo = 0, hi = n, j = 0; j < hi; ) {
    if (v[j] < x) {
      swap(v, lo, j); ++lo; ++j;
    } else if (v[j] > x) {
      --hi; swap(v, j, hi);
    } else {
      ++j;
    }
  }

还有另一种算法,由Bentley和McIlroy于1993年发现并发表在他们的论文"Engineering a Sort Function"中,其中有一些很好的图表说明了各种分区函数的工作原理,以及一些关于分区算法为何重要的讨论。宾利&amp;如果枢轴元素在列表中不常出现,则McIlroy算法更好,而Dijkstra在经常出现时更好,因此您必须了解有关数据的信息才能在它们之间进行选择。我相信大多数现代快速排序算法都使用Bentley&amp; McIlroy,因为常见的情况是要排序的数组几乎没有重复。

注释

  1. Wikipedia Quicksort article中提供的Hoare算法不会重新排列等于枢轴的值,因此它们最终会出现在两个分区中。因此,它不是真正的分区算法。

答案 1 :(得分:1)

你可以这样做:
1)循环遍历数组,如果element小于x,则将其放入新的array1中 2)如果元素大于x,则放入新的array2 这是线性时间O(n)

答案 2 :(得分:0)

我尝试过下面这样的事情,我认为是O(n)。我花了一点时间来解决这个问题,但我认为它与上面的荷兰标志答案非常相似。

我的ouptput

a.exe
1 4 6 5 3 1 7 7 11 13 
1 4 5 6 3 1 7 7 7 11 13 

代码:

#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
void order(int * list, int size, int orderVal)
{
  int firstIdx, lastIdx, currVal, tempVal;

  firstIdx = 0;
  lastIdx = size-1;

  for ( ;lastIdx>firstIdx;firstIdx++)
  {
      currVal = list[firstIdx];
      if (currVal >= orderVal)
      {
        tempVal = list[lastIdx];
        list[lastIdx] = currVal;
        lastIdx--;
        list[firstIdx] = tempVal;
        if (tempVal >= orderVal)
          firstIdx--;
      }  
  }
  lastIdx = size-1;

  for( ;lastIdx>firstIdx && middleNum>0;lastIdx--)
  {
      currVal = list[lastIdx];
      if (currVal == orderVal)
      {
        tempVal = list[firstIdx];
        list[firstIdx] = currVal;
        firstIdx++;
        list[lastIdx] = tempVal;
        if (tempVal == orderVal)
          lastIdx++;
      }
   }
}

int main(int argc, char * argv[])
{
  int i;
  int list[] = {1, 4, 6, 7, 13, 1, 7, 3, 5, 11};
  int list2[] = {1, 4, 7, 6, 7, 13, 1, 7, 3, 5, 11};

  order(list, ARRAY_SIZE(list), 7);

  for (i=0; i<ARRAY_SIZE(list); i++)
    printf("%d ", list[i]);
  printf("\n");

  order(list2, ARRAY_SIZE(list2), 7);

  for (i=0; i<ARRAY_SIZE(list2); i++)
    printf("%d ", list2[i]);
}

答案 3 :(得分:-1)

以下是使用冒泡排序的示例。哪种类型的排序算法最好,取决于您,这只是为了演示。在这里,我对待价值&lt; x为-1,值== x为0,值为&gt; x为1

注意元素&lt; x和那些&gt; x仍然是相同的序列。

#include <stdio.h>

int main(void)
{   
    int array[] = { 1, 4, 6, 7, 13, 1, 7, 3, 5, 11 };
    int x = 7;
    int len = sizeof array / sizeof array[0];
    int i, j, m, n, tmp;

    for (i=0; i<len-1; i++) {
        m = array[i] < x ? -1 : array[i] == x ? 0 : 1;
        for (j=i+1; j<len; j++) {
            n = array[j] < x ? -1 : array[j] == x ? 0 : 1;
            if (m > n) {
                tmp = array[i];         // swap the array element
                array[i] = array[j];
                array[j] = tmp;
                m = n;                  // and replace alias
            }
        }
    }

    for(i=0; i<len; i++)
        printf("%d ", array[i]);
    printf("\n");

    return 0;
}

节目输出:

1 4 6 1 3 5 7 7 13 11