繁体   English   中英

C-自定义qsort不起作用

[英]C - Custom qsort not working

我正在尝试使具有相同参数的qsort类型的函数。 我还编写了3个函数来比较int,float和character。 由于某种原因,它在任何情况下都不起作用。 我不知道这是我的qsortx函数是否存在问题,但是我检查了几次,它应该可以正常工作。 我不确定是什么问题,还是我做错了。 我目前正在学习函数指针,但可能没有与之相关的所有东西。 提前致谢。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void qsortx(void*, int, int, int (*)(const void*, const void*));
int intcmp();
int floatcmp();
int charcmp();

int main()
{
    int i,n;
    char items[]={'c', 'a', 'b'};
    n = 3;
    for (i=0;i<n;++i) {
        printf("%c ", items[i]);
    }
    printf("\n");

    qsortx(items, n, sizeof(char), charcmp);

    for (i=0;i<n;++i) {
        printf("%c ", items[i]);
    }
    printf("\n");
    return 0;
}

void qsortx (void *tp, int length, int pace, int(*fp)(const void* a, const void* b)) {
    int switched,i,j;
    void *p;
    p=(void*)malloc(pace);
    switched = 1;
    while (1) {
        if (switched == 0) {
            return;
        }
        switched = 0;
        for (i=0; i<length-1;++i) {
            for (j=0;j<length-1;++j) {
                printf("%c %c", tp+i, tp+j);
                if (fp(tp+i, tp+j) > 0) {
                    memcpy(p, tp+i, pace);
                    memcpy(tp+i, tp+j, pace);
                    memcpy(tp+j, p, pace);
                    switched++;
                }
            }
        }

    }
}

int intcmp(const void* a, const void* b) {
    return *(int*)a - *(int*)b;
}

int floatcmp(const void* a, const void* b) {
    return *(float*)a - *(float*)b;
}

int charcmp(const void* a, const void* b) {
    return *(char*)a - *(char*)b;
}

您有多个与指针算术和元素大小有关的问题。 您的排序中也有一个逻辑错误(我想您知道这是一个单向振动器排序)。 这是qsortx()函数的版本,可解决这些缺陷:

void qsortx (void *tp, int length, int pace, int(*fp)(const void* a, const void* b)) {
    if (length > 1) {
        char *bound = ((char *) tp) + (length * pace);
        char *p = malloc(pace);
        char *item1p;

        for (item1p = tp; item1p < (bound - pace); item1p += pace) {
            char *item2p;

            for (item2p = item1p + pace; item2p < bound; item2p += pace) {
                if (fp(item1p, item2p) > 0) {
                    memcpy(p, item1p, pace);
                    memcpy(item1p, item2p, pace);
                    memcpy(item2p, p, pace);
                }
            }
        }

        free(p);
    }
}

注意:

  1. 所有指针运算都是对char *类型的值执行的。
  2. 在遍历输入数组时,必须考虑元素大小( pace ),否则您只会打乱数据。
  3. 最内层的循环应从下一个外层循环中考虑的元素之后的元素开始。
  4. switched ++相比, switched = 1是更好的选择,因为它不会溢出,并且您关心的只是零与非零。 (更新:但是switched不再重要。)
  5. (更新)如果通过item1p循环导致零交换,则提早退出是不正确的。 仅仅因为一个元素已经在其正确的位置并不意味着所有后续元素也都在其正确的位置。 我更新了上面的代码以删除该行为。
  6. (更新)正如chux所观察到的,为交换元素保留的临时空间未释放。 我添加了一个适当的free(p)
  7. (更新)我还以数组长度大于1为条件进行排序,这样可以避免与bound - pace相关的不确定行为(如果length为零)。

这是快速排序(qsort)算法的伪代码和实现,以及一些辅助代码,如http://www.codingbot.net/2013/01/quick-sort-algorithm-and-c-code中所定义。 html网页:请注意,此算法与qsort()稍有不同,因为它具有不同的参数列表和某些其他详细信息。 但是,基本算法是相同的。

function quicksort('array')
    if length('array') ≤ 1
        return 'array'  // an array of zero or one elements is already sorted
        select and remove a pivot value 'pivot' from 'array'
        create empty lists 'less' and 'greater'
        for each 'x' in 'array'
            if 'x' ≤ 'pivot' 
                then append 'x' to 'less'
            else 
                append 'x' to 'greater'
            endif
        end for
        return concatenate(quicksort('less'), 'pivot', quicksort('greater') );

notice that qsort is a partition sort, using recursion.

#include<stdio.h>
#include<conio.h>

void quick_sort(int arr[20],int,int);

int main()
{
   int arr[20],n,i;
   clrscr();
   printf("Enter the number of elements in the Array: ");
   if( 1 != scanf(" %d",&n) ) 
   {
       perror( "scanf for count of elements" );
       exit(1);
   }

   printf("\nEnter %d elements:\n\n",n);

   for(i=0 ; i<n ; i++)
   {
        printf(" Array[%d] = ",i);
        if( 1 != scanf(" %d",&arr[i]) )
        {
            perror( "scanf for element values" );
            exit(2);
        }

   }

   quick_sort(arr,0,n-1);
   printf("\nThe Sorted Array is:\n\n");

   for(i=0 ; i<n ; i++)
   {
        printf(" %4d",arr[i]);
   }
   getch();
}

void quick_sort(int arr[20],int low,int high)
{
    int pivot; // used in partitioning the array
    int j; // loop index
    int temp; // for swapping
    int i; // loop index

    if(low<high)
    {
        pivot = low; 
        i = low;
        j = high;

        while(i<j)
        {
            // find next item not in proper sequence
            while((arr[i] <= arr[pivot]) && (i<high))
            {
                i++;
            }

            // find next item not in proper sequence
            while(arr[j] > arr[pivot])
            {
                j--;
            }

            // following is where a callback function would be invoked
            if(i<j)
            { 
                temp=arr[i];
                arr[i]=arr[j];
                arr[j]=temp;
            }
        }

        temp=arr[pivot];
        arr[pivot] = arr[j];
        arr[j]=temp;

        // following is where recursion is used to perform sort on sub partitions
        quick_sort(arr,low,j-1);
        quick_sort(arr,j+1,high);
   }
}

对于您的目的,这是一种更好的算法。 但是,它仅处理整数,因此您需要将比较函数作为第4个参数添加到quicksort()并修改代码以使用比较函数

#include <stdio.h>
#include <stdlib.h>

void swap(int *x,int *y);
int choose_pivot(int i,int j );
void quicksort(int list[],int m,int n);
void display(int list[],const int n);

int main()
{
    const int SIZE = 10;
    int list[SIZE];

    int i = 0;

    /* generates random numbers and fill the list */
    for(i = 0; i < SIZE; i++ )
    {
        list[i] = rand();
    }

    printf("The list before sorting is:\n");
    display(list,SIZE);

    /* sort the list using quicksort algorithm */
    quicksort(list,0,SIZE-1);

    printf("The list after sorting:\n");
    display(list,SIZE);
}


void swap(int *x,int *y)
{
    // for integer swaps, 3 exclusive OR operations would be much faster
    // and not require a temp variable
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
}


int choose_pivot(int i,int j )
{
    return((i+j) /2);
}


void quicksort(int list[],int m,int n)
{
    int key,i,j,k;

    if( m < n)
    {
        k = choose_pivot(m,n);
        swap(&list[m],&list[k]);
        key = list[m];
        i = m+1;
        j = n;
        while(i <= j)
        {
            while((i <= n) && (list[i] <= key))
            {
                 i++;
            }

            while((j >= m) && (list[j] > key))
            {
                j--;
            }

            if( i < j)
            {
                swap(&list[i],&list[j]);
            }
        }

        /* swap two elements */
        swap(&list[m],&list[j]);

        /* recursively sort the lesser list */
        quicksort(list,m,j-1);
        quicksort(list,j+1,n);
    }
}


void display(int list[],const int n)
{
    int i;

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

暂无
暂无

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

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