按坐标与原点的距离对坐标数组进行排序

时间:2013-12-15 18:08:16

标签: c arrays sorting

代码应该从用户获取一个坐标数组,然后对该数组进行排序,将坐标按它们与原点的距离的顺序排列。我相信我的问题在于排序功能(我使用了快速排序)。

我正在尝试自己编写函数以更好地理解它,这就是为什么我没有使用qsort()

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

#define MAX_SIZE 64

typedef struct
{
    double x, y;
}POINT;

double distance(POINT p1, POINT p2);
void sortpoints(double distances[MAX_SIZE], int firstindex, int lastindex, POINT data[MAX_SIZE]);
void printpoints(POINT data[], int n_points);

int main()
{    
    int n_points, i;
    POINT data[MAX_SIZE], origin = { 0, 0 };
    double distances[MAX_SIZE];

    printf("How many values would you like to enter?\n");
    scanf("%d", &n_points);

    printf("enter your coordinates\n");

    for (i = 0; i < n_points; i++)
    {
        scanf("%lf %lf", &data[i].x, &data[i].y);
        distances[i] = distance(data[i], origin); //data and distances is linked by their index number in both arrays
    }

    sortpoints(distances, 0, i, data);

    return 0;
}

double distance(POINT p1, POINT p2)
{
    return sqrt(pow((p1.x - p2.x), 2) + pow((p1.y - p2.y), 2));
}

void printpoints(POINT *data, int n_points)
{
    int i;

    printf("Sorted points (according to distance from the origin):\n");

    for (i = 0; i < n_points; i++)
    {
        printf("%.2lf %.2lf\n", data[i].x, data[i].y);
    }
}

//quicksort
void sortpoints(double distances[MAX_SIZE], int firstindex, int lastindex, POINT data[MAX_SIZE])
{
    int indexleft = firstindex;
    int indexright = lastindex;
    int indexpivot = (int)((lastindex + 1) / 2);
    int n_points = lastindex + 1;
    double left = distances[indexleft];
    double right = distances[indexright];
    double pivot = distances[indexpivot];
    POINT temp;

    if (firstindex < lastindex) //this will halt the recursion of the sorting function once all the arrays are 1-size
    {

        while (indexleft < indexpivot || indexright > indexpivot) //this will stop the sorting once both selectors reach the pivot position
        {
            //reset the values of left and right for the iterations of this loop
            left = distances[indexleft];
            right = distances[indexright];

            while (left < pivot)
            {
                indexleft++;
                left = distances[indexleft];
            }

            while (right > pivot)
            {
                indexright--;
                right = distances[indexright];
            }

            distances[indexright] = left;
            distances[indexleft] = right;

            temp = data[indexleft];
            data[indexleft] = data[indexright];
            data[indexright] = temp;
        }

        //recursive sorting to sort the sublists
        sortpoints(distances, firstindex, indexpivot - 1, data);
        sortpoints(distances, indexpivot + 1, lastindex, data);
    }

    printpoints(data, n_points);
}

感谢您的帮助,我一直在尝试调试这几个小时,甚至使用调试器。

3 个答案:

答案 0 :(得分:2)

哎哟!您以sortpoints()为参数调用i。根据您的原型和代码,该论点应为last index,而i不是last index,而是last index + 1

int indexleft = firstindex;
int indexright = lastindex;   // indexright is pointing to a non-existent element.
int indexpivot = (int)((lastindex + 1) / 2);
int n_points = lastindex + 1;
double left = distances[indexleft];
double right = distances[indexright];  // now right is an undefined value, or segfault.

要解决此问题,请将您的sortpoints()功能称为:

 sortpoints (0, n_points-1, data);

答案 1 :(得分:0)

问题出在您的sortpoints功能中。第一个while循环无限循环。要测试它是无限循环还是不放置printf语句

printf("Testing first while loop\n"); 

在您的第一个while循环中。你必须解决这个问题。

答案 2 :(得分:0)

有很多问题,但其中一个是:

int indexpivot = (int)((lastindex + 1) / 2);

演员阵容是不必要的,但这是琐事。更为基本的是,如果你从48..63中对一个片段进行排序,你将在元素32上进行旋转,这不在你应该处理的范围内。你需要使用:

int indexpivot = (lastindex + firstindex) / 2;

或者也许:

int indexpivot = (lastindex + firstindex + 1) / 2;

对于示例范围,它们将在元素55或56上进行旋转,这至少在范围内。

我强烈建议:

  • 创建类似于printpoints()的打印功能,但有以下不同之处:

    1. 使用'tag'字符串来标识它正在打印的内容。
    2. 也拍摄并打印距离数组。
    3. 获取数组和一对偏移量。
  • 在递归之前在sort函数中使用此函数。

  • 在返回之前在sort函数中使用此函数。
  • 阅读完数据后,在主函数中使用此功能。
  • 在对数据进行排序后,在main函数中使用此函数。
  • 打印键值 - 枢轴距离,枢轴索引,在适当的位置。

这允许您检查分区是否正常工作(目前不是)。

然后,当您的代码正常工作时,您可以在排序功能中删除或禁用(注释掉)打印代码。