您的位置:首页 > 编程语言

《算法导论》笔记:第2章 思考题2-4 求逆序对(代码)

2015-01-27 23:26 190 查看
逆序对的定义:设A[1…n]是一个包含n个不同数的数组。如果在i<j的情况下,有A[i]>A[j],则(i,j)就称为A中的一个逆序对(inversion)。

要求给出一个算法,它能用Θ(nlgn)的最坏情况运行时间,确定n个元素的任何排列中逆序对的数目。

下面是c代码实现,采用合并排序算法。此代码尚未经过优化,仅供参考。

inversion.h

/*
* Caculate the number of inversions in the array
* 求数组中的逆序对的个数
*/

#ifndef _FENGHOU_INVERSION_H_
#define _FENGHOU_INVERSION_H_

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

long calc_inversion(int * array, int length);

#endif /* _FENGHOU_INVERSION_H_ */


inversion.c

#include "inversion.h"

#include <string.h>

int * _calc_inversion_merge_sort(int * array, int length, long * inversion);
int * _calc_inversion_merge(int * array_left, int length_left, int * array_right, int length_right, long * inversion);
void _calc_inversion_print_new_array(int * array, int length);

long calc_inversion(int * array, int length)
{
assert(array && length > 0);

long inversion = 0;

int mid = length / 2;

int * array_left = _calc_inversion_merge_sort(array, mid, &inversion);
int * array_right = _calc_inversion_merge_sort(array + mid, length - mid, &inversion);
int * array_new = _calc_inversion_merge(array_left, mid, array_right, length - mid, &inversion);

if (mid > 1) free(array_left);
if (length - mid > 1) free(array_right);

_calc_inversion_print_new_array(array_new, length);
free(array_new);

return inversion;
}

int * _calc_inversion_merge_sort(int * array, int length, long * inversion)
{
if (length == 1) return array;

int mid = length / 2;

int * array_left = _calc_inversion_merge_sort(array, mid, inversion);
int * array_right = _calc_inversion_merge_sort(array + mid, length - mid, inversion);
int * array_new = _calc_inversion_merge(array_left, mid, array_right, length - mid, inversion);

if (mid > 1) free(array_left);
if (length - mid > 1) free(array_right);

return array_new;
}

int * _calc_inversion_merge(int * array_left, int length_left, int * array_right, int length_right, long * inversion)
{
int * array_new = (int *)malloc((length_left + length_right) * sizeof(int));

int i = 0, l = 0, r = 0;
while (l < length_left && r < length_right)
{
if (array_left[l] <= array_right[r])
array_new[i++] = array_left[l++];
else
{
array_new[i++] = array_right[r++];
*inversion += (length_left - l);
printf("Sub-array length: %d, %d\t\tinversions: +%d\n", length_left, length_right, length_left - l);
}
}

if (l == length_left)
memcpy(array_new + i, array_right + r, (length_right - r) * sizeof(int));
else
memcpy(array_new + i, array_left + l, (length_left - l) * sizeof(int));

return array_new;
}

void _calc_inversion_print_new_array(int * array, int length)
{
printf("Sorted array: [");
for (int i = 0; i < length; ++i)
{
printf("%d", array[i]);
if (i != length - 1) printf(", ");
}
printf("]\n");
}


main.c

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

#include "inversion.h"

int main(void)
{
int array[] = {8, 7, 6, 5, 4, 3, 2, 1};

long inversion = calc_inversion(array, sizeof(array) / sizeof(int));

printf("Number of inversions: %ld\n", inversion);

exit(0);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: