简体   繁体   English

快速排序比较计数间歇结果

[英]quicksort comparison count intermittent results

SOLUTION the solution is unique to my code -- I placed srand(time(NULL)); 解决方案该解决方案对我的代码是唯一的-我放置了srand(time(NULL)); inside the loop when it should've been placed outside 应该放在循环内时


I'm trying to count the number of comparisons in a quick sort algorithm. 我正在尝试计算快速排序算法中比较的次数。 I had a recursive version working fine, but it kept seg faulting because I was using large array sizes -- running out of stack space. 我有一个递归版本,可以正常工作,但是由于我使用的是大数组大小-堆栈空间用完了,所以它一直存在段错误。

So now I've resulted to an iterative approach, and it works. 因此,现在我得到了一种迭代方法,并且它行得通。 That is, except for my counter for the number of comparisons. 也就是说,除了我的比较次数计数器。

It's returning intermittent results such as... 它返回间歇性结果,例如...

unsorted: [9][8][7][6][5][4][3][2][1][0]
sorted: [0][1][2][3][4][5][6][7][8][9]
Numer of comparisons: 22

unsorted: [9][8][7][6][5][4][3][2][1][0]
sorted: [0][1][2][3][4][5][6][7][8][9]
Numer of comparisons: 19749794

unsorted: [9][8][7][6][5][4][3][2][1][0]
sorted: [0][1][2][3][4][5][6][7][8][9]
Numer of comparisons: 6088231

my code for the iterative quick sort is... 我的迭代快速排序代码是...

#include <time.h>
#define BUFLEN 6400

extern int buf[BUFLEN];
extern int quick_count; //comparison count

struct stack {
    int stk[BUFLEN];
    int top;
};

struct stack s;

void push(int x);
int pop();

void iterative_quick_sort (int buf[], int n) {
    int left_ptr, right_ptr, pivot_index, pivot, temp, l, r;
    if (n < 2) //case the partitioning has reached the atomic element
        return;
    r = n - 1;
    l = 0;
    s.top = -1;
    loop: do{
      srand(time(NULL));
      if ((r - l) == 0)
        pivot_index = 1;
      else {
        pivot_index = rand() % (r - l);
        pivot_index += l;
      }
      pivot = buf[pivot_index]; //pivot holds the value of the pivot element
      left_ptr = l;
      right_ptr = r;
      if ((r - l) != 0 || (r - l) != 1){
        while (1) {
            while (buf[left_ptr] < pivot){ //loop and increment left_ptr until an element on the left side is larger than the pivot
              left_ptr++;
            } //now left_ptr holds the index of the value that needs to be swapped with an element from the right side
            while (pivot < buf[right_ptr]){ //loop and increment right_ptr until an element on the right side is smaller than the pivot
              right_ptr--;
            } //now right_ptr holds the index of the value that needs to be swapped with an element from the left side
            quick_count++;
            if (left_ptr >= right_ptr)
                break; //once the pivots reach or overlap each other, break the loop
            //perform swap with temporary variable temp
            temp = buf[left_ptr];
            buf[left_ptr] = buf[right_ptr];
            buf[right_ptr] = temp;
        }
      }

      if (l == (n - 2))
        break;
      else if ((r - l) >= 2){
        //goto loop with left side values
        push(r);
        r = pivot_index + 1;
        goto loop;
      }
      else {
        //goto loop with right side values
        l = r;
        r = pop();
        goto loop;
      }
  }while(1);
}

//cite http://www.sanfoundry.com/c-program-stack-implementation/
void push (int x){
    s.top = s.top + 1;
    s.stk[s.top] = x;
}

int pop(){
    int x = s.stk[s.top];
    s.top = s.top - 1;
    return x;
}

per request, I've added the function that calls quick sort (Note: quick_count is initialized to zero as a global variable -- used as an extern) 对于每个请求,我添加了调用快速排序的函数(注意: quick_count作为全局变量初始化为零-用作外部变量)

int unsorted_quick[] = {9,8,7,6,5,4,3,2,1,0}; //n = 10
//print unsorted_quick
  printf("\nSecond, we sort the following array by using the quick sort algorithm\n");
  for (i = 0; i < 10; i++){
    printf("[%d]", unsorted_quick[i]);
  }
  printf("\n");

  //fill buf with the unsorted quick array
  for (i = 0; i < 10; i++){
    buf[i] = unsorted_quick[i];
  }

  iterative_quick_sort(buf, 10); //call quick_sort()

  //print sorted
  for (i = 0; i < 10; i++){
    printf("[%d]", buf[i]);
  }
  printf("\nNumber of comparisons: %d\n", quick_count);  //print count

You are calling srand(time(NULL)) inside the loop that choose the random pivot. 您正在循环内调用srand(time(NULL)),以选择随机枢轴。 This function must be called once to initialise the state of the random number generator. 必须调用一次此函数以初始化随机数生成器的状态。 The generator needs a starting seed which is set by calling srand(). 生成器需要一个起始种子,该种子可以通过调用srand()来设置。 Then, given the seed, each subsequent call to rand() will give you a random number in a reproducible sequence. 然后,给定种子,随后对rand()的每次调用都会为您提供可重复序列的随机数。 Starting from the same seed you will get the same random sequence. 从相同的种子开始,您将获得相同的随机序列。

The problem is that you set the seed in the loop and the seed is the same number so you will always get the same "random" value. 问题是您在循环中设置了种子,并且种子是相同的数字,因此您将始终获得相同的“随机”值。 This happens because time(NULL) is taken from current time in seconds which means that the random number it's the same in the same second. 发生这种情况是因为time(NULL)是从当前时间(以秒为单位)中获取的,这意味着随机数在同一秒内是相同的。

You must put it before the loop: do { 您必须将其放在循环之前:do {

Here there is a nice explanation of what is happening: Problems when calling srand(time(NULL)) inside rollDice function 这里对发生的事情有一个很好的解释: 在rollDice函数中调用srand(time(NULL))时出现问题

And also here: srand() — why call it only once? 还有这里: srand()-为什么只调用一次?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM