1. 程式人生 > >歸併排序 && 外部排序

歸併排序 && 外部排序

基本思想 先對資料進行均分------>左右兩半部分------->均分到左右部分已經有序------>歸併

歸併排序核心步驟: 分組 歸併 在這裡插入圖片描述 MergeSort.h

#ifndef __MERGESORT_H__
#define __MERGESORT_H__

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

void _MergeSort(int* array, int left, int right, int* temp);
void MergeData(int* array, int left, int mid, int right, int* temp);
void MergeSort(int* array, int size);
//外部排序
void MergeSortNor(int* array, int size);
void Print(int* array, int size);


#endif //__MERGESORT_H__

MergeSort.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"MergeSort.h"

void Print(int* array, int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		printf("%d ", array[i]);
	}
	printf("\n");
}

void MergeData(int* array, int left, int mid, int right, int* temp)
{
	int begin1 = left, end1 = mid;
	int begin2 = mid, end2 = right;//begin2不取到mid是因為中間數不用排序,只需要排它的左右
	int index = left;
	while (begin1 < end1 && begin2 < end2)
	{
		if (array[begin1] <= array[begin2])
			temp[index++] = array[begin1++];
		else
			temp[index++] = array[begin2++];
	}
	while (begin2 < end2)
		temp[index++] = array[begin2++];
	while (begin1 < end1)
		temp[index++] = array[begin1++];
}

void _MergeSort(int* array, int left, int right, int* temp)
{
	if (right - left > 1)//當區間內只剩兩個元素的時候就不能再分了,因為是兩兩合併,左右區間最少各有一個元素
	{
		int mid = left + ((right - left) >> 1);
		_MergeSort(array, left, mid, temp);
		_MergeSort(array, mid, right, temp);
		MergeData(array, left, mid, right, temp);
		memcpy(array + left, temp + left, (right - left) * sizeof(int));
	}
}

void MergeSort(int* array, int size)
{
	int* temp = (int*)malloc(size * sizeof(int));
	if (NULL == temp)
	{
		printf("開闢空間失敗\n");
		return;
	}
	_MergeSort(array, 0, size, temp);
	free(temp);
}

void MergeSortNor(int* array, int size)
{
	int* temp = (int*)malloc(size * sizeof(int));
	int i = 0;
	int gap = 1;
	int left = 0;
	int right = 0;
	int mid = 0;
	while (gap < size)
	{
		for (i = 0; i < size; i += 2 * gap)
		{
			//計算左右兩半部分割槽間
			left = i;
			mid = i + gap;
			right = mid + gap;
			//檢測左右半部分割槽間的合法性
			if (mid > size)
				mid = size;
			if (right > size)
				right = size;
			MergeData(array, left, mid, right, temp);
			memcpy(array + left, temp + left, (right - left) * sizeof(int));
		}
		gap = gap * 2;
	}
	free(temp);
	temp = NULL;
}


test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"MergeSort.h"

int main()
{
	int array[] = { 4, 0, 3, 5, 9, 7, 6, 1, 2, 8 };
	int size = sizeof(array) / sizeof(array[0]);
	//MergeSort(array, size);
	MergeSortNor(array, size);
	Print(array, size);
	return 0;
}