合併排序演算法實作
特徵
1. 為 Stable 排序。
2. 因為需要額外空間,非 in-place algorithm。
** in-place algorithm 指的是使用較少空間處理的演算法。
(In-place is an algorithm which transforms input using a data structure with a small, constant amount of extra storage space.)
出處:維基百科
實作重點 (KEY POINT)
1. 進行分割 (直到無法再分割為止,以 "/2" 作為索引持續分割) lgN
2. 進行合併 (將分割後的值重新聚合,聚合的同時進行比較並排序) N
速度:N * lgN
以下為實作程式碼。
/**
* Algorithm Course
*
* Homework Assignement #3
* - find number of inversions in an arr (from input file with integers)
*
* @student ID: A889056
* @name : GiPyeongLee
* @.agents/skills/caveman-compress/scripts/validate.py : 2015.03.16
**/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#include "errno.h"
#include "sys/time.h"
#define MAX_NUM 1000000
unsigned long cnt = 0;
void seperate(int *arr,int left,int right);
void merge(int *arr,int left,int mid,int right);
void count_inversion (int *data, int left, int right) {
seperate(data,left,right); // seperate and merge
}
void seperate(int *arr,int left,int right){
if(left < right){
int mid;
mid=(left+right)/2;
seperate(arr,left,mid);
seperate(arr,mid+1,right);
merge(arr,left,mid,right);
}
}
void merge(int *arr,int left,int mid,int right){
int tempArr[right-left+1];
int pos=0,lpos = left,rpos = mid + 1;
while(lpos <= mid && rpos <= right)
{
if(arr[lpos] < arr[rpos])
{
tempArr[pos++] = arr[lpos++];
}
else
{
cnt+=(mid-lpos+1);
tempArr[pos++] = arr[rpos++];
}
}
while(lpos <= mid) tempArr[pos++] = arr[lpos++];
while(rpos <= right)tempArr[pos++] = arr[rpos++];
int iter;
// iterator to pos , tempArr to arr.
for(iter = 0;iter < pos; iter++)
{
arr[iter+left] = tempArr[iter];
}
return;
}
int main(int argc, char *argv[]) {
char *filename;
FILE *fp;
char str[10];
int number;
unsigned int N;
int data[MAX_NUM] = {};
clock_t start_time,end_time;
if (argc > 1) {
filename = argv[1];
} else {
printf("no input file argument\n");
return -1;
}
if ((fp = fopen(filename, "r")) == NULL) {
printf("Error opening input file\n");
return -1;
}
while (fgets(str, 10, fp) != NULL) {
if (N >= MAX_NUM) {
printf("too many data\n");
break;
}
number = strtol(str, NULL, 10);
if (errno == EINVAL)
break;
data[N] = number;
N++;
}
start_time=clock();
printf("INPUT : Number of data N = %d\n", N);
count_inversion(data, 0, N - 1);
printf("OUTPUT: Number of inversions = %lu\n", cnt);
end_time = clock();
printf("running time = %f seconds\n",((double)(end_time-start_time))/CLOCKS_PER_SEC);
return 0;
}
透過上述合併排序完成了作業,該作業要求計算反轉 (Inversion) 的總情況數。
使用上述程式碼,得到了以下的結果。
顯示更多
$ ./count_inversions hw3_input_10k.txt INPUT : Number of data N = 10000 OUTPUT: Number of inversions = 23948130 running time = 0.002207 seconds $ $ ./count_inversions hw3_input.txt INPUT : Number of data N = 100000 OUTPUT: Number of inversions = 2407905288 running time = 0.019184 seconds $ $ ./count_inversions hw3_input_1000k.txt INPUT : Number of data N = 1000000 OUTPUT: Number of inversions = 249953281796 running time = 0.227101 seconds