C源码@数据结构与算法->Sorting

/*
 * testsort.cpp
 */
#include 
   
   
    
    
#include 
    
    
     
     
#include "sort.h"

ElementType Arr[] = {34, 8, 64, 51, 32, 21, 0, 100, 99, 3};

void Permute(ElementType A[], int N)
{
	int i;

	for (i = 0; i < N; ++i)
	{
		A[i] = i;
	}
	for (i = 1; i < N; ++i)
	{
		Swap(&A[i], &A[rand() % (i + 1)]);
	}
}

void CheckSort(ElementType A[], int N, const char *SortType)
{
	int i;

	for (i = 0; i < N; ++i)
	{
		if (A[i] != i)
		{
			printf("%sSort fails: %d %d\n", SortType, i, A[i]);
		}
	}
}

void Copy(ElementType Lhs[], const ElementType Rhs[], int N)
{
	int i;

	for (i = 0; i < N; ++i)
	{
		Lhs[i] = Rhs[i];
	}
}

#define MaxSize (7000)
int Arr1[MaxSize];
int Arr2[MaxSize];

int main()
{
	int i;

	for (i = 0; i < 10; ++i)
	{
		Permute(Arr2, MaxSize);

		Copy(Arr1, Arr2, MaxSize);
		InsertionSort(Arr1, MaxSize);
		CheckSort(Arr1, MaxSize, "Insertion");

		Copy(Arr1, Arr2, MaxSize);
		ShellSort(Arr1, MaxSize);
		CheckSort(Arr1, MaxSize, "Shell");

		Copy(Arr1, Arr2, MaxSize);
		HeapSort(Arr1, MaxSize);
		CheckSort(Arr1, MaxSize, "Heap");

		Copy(Arr1, Arr2, MaxSize);
		MergeSort(Arr1, MaxSize);
		CheckSort(Arr1, MaxSize, "Merge");

		Copy(Arr1, Arr2, MaxSize);
		QuickSort(Arr1, MaxSize);
		CheckSort(Arr1, MaxSize, "Quick");

		Copy(Arr1, Arr2, MaxSize);
		QSelect(Arr1, MaxSize / 2 + 1 + i, 0, MaxSize - 1);
		if (Arr1[MaxSize / 2 + i] != MaxSize / 2 + i)
		{
			printf("Select error: %d %d\n", 
				MaxSize / 2 + i, Arr1[MaxSize / 2 + i]);
		}

		Permute(Arr2, MaxSize);
		Copy(Arr1, Arr2, MaxSize);
		RadixSort(Arr1, MaxSize);
		CheckSort(Arr1, MaxSize, "Radix");
	}

	return 0;  
}
    
    
   
   
/*
 * fatal.h
 */
#include 
    
    
     
     
#include 
     
     
      
      

#define Error(Str)		FatalError(Str)
#define FatalError(Str)	fprintf(stderr, "%s\n", Str), exit(-1)	
     
     
    
    
/*
 * sort.h
 */
#ifndef _SORT_H
#define _SORT_H

#ifndef NULL
#define NULL (0)
#endif

typedef int ElementType;

#ifdef __cplusplus
extern "C" {
#endif

void Swap(ElementType *Lhs, ElementType *Rhs);
void InsertionSort(ElementType A[], int N);
void ShellSort(ElementType A[], int N);
void HeapSort(ElementType A[], int N);
void MergeSort(ElementType A[], int N);
void QuickSort(ElementType A[], int N);
void QSelect(ElementType A[], int k, int Left, int Right);

void RadixSort(ElementType A[], int N);

#ifdef __cplusplus
}
#endif

#endif /* _SORT_H */
/*
 * sort.cpp
 */
#include 
    
    
     
     
#include "fatal.h"
#include "sort.h"

void Swap(ElementType *Lhs, ElementType *Rhs)
{
	/* if Lhs && Rhs point to same variable, *Lhs && *Rhs will be all 0 */
	if (Lhs == Rhs)
	{
		return;
	}

	*Lhs ^= *Rhs;
	*Rhs ^= *Lhs;
	*Lhs ^= *Rhs;
}

/*---------------------------InsertionSort------------------------------*/

/*
 * For pass P = 1 through N - 1, insertion sort ensures that 
 * elements in position 0 through P are in sorted order.
 * In Pass P, we move the element in position P left until 
 * its right place is found among the first P + 1 elements.
 */
void InsertionSort(ElementType A[], int N)
{
	int j, P;
	ElementType Tmp;

	/* The element in position P is saved in Tmp, and all larger elements */
	/* (prior to position P) are moved one spot to the right. */
	/* Then Tmp is placed in the correct spot. */
	for (P = 1; P < N; ++P)
	{
		Tmp = A[P];
		for (j = P; j > 0 && A[j - 1] > Tmp; --j)
		{
			A[j] = A[j - 1];
		}
		A[j] = Tmp;
	}
}

/*---------------------------ShellSort------------------------------*/

void ShellSort(ElementType A[], int N)
{
	int i, j, Increment;
	ElementType Tmp;

	for (Increment = N / 2; Increment > 0; Increment /= 2)
	{
		for (i = Increment; i < N; ++i)
		{
			Tmp = A[i];
			for (j = i; j >= Increment; j -= Increment)
			{
				if (Tmp < A[j - Increment])
				{
					A[j] = A[j - Increment];
				}
				else
				{
					break;
				}
			}
			A[j] = Tmp;
		}
	}
}

/*---------------------------HeapSort------------------------------*/

/*
 * The array for HeapSort contains data from position 0. 
 */
#define LeftChild(i) (2 * (i) + 1)

static void PercolateDown(ElementType A[], int i, int N)
{
	int Child;
	ElementType Tmp;

	/* Two comparisons: one to find the smaller child */
	/* and one to compare the smaller child with the node*/
	for (Tmp = A[i]; LeftChild(i) < N; i = Child)
	{
		Child = LeftChild(i);

		if (Child != N - 1 && A[Child + 1] > A[Child])
		{
			++Child;
		}

		if (Tmp < A[Child])
		{
			A[i] = A[Child];
		}
		else
		{
			break;
		}
	}
	A[i] = Tmp;
}

void HeapSort(ElementType A[], int N)
{
	int i;

	/* Build heap */
	for (i = N / 2; i >= 0; --i)
	{
		PercolateDown(A, i, N);
	}

	/* Delete Max */
	for (i = N - 1; i > 0; --i)
	{
		Swap(&A[0], &A[i]);
		PercolateDown(A, 0, i);
	}
}

/*---------------------------MergeSort------------------------------*/

/*
 * Lpos = start of left half, Rpos = start of right half.
 */
void Merge(ElementType A[], ElementType TmpArray[],
	int Lpos, int Rpos, int RightEnd)
{
	int i, LeftEnd, NumElements, TmpPos;

	LeftEnd = Rpos - 1;
	TmpPos = Lpos;
	NumElements = RightEnd - Lpos + 1;

	/* main loop */
	while (Lpos <= LeftEnd && Rpos <= RightEnd)
	{
		if (A[Lpos] <= A[Rpos])
		{
			TmpArray[TmpPos++] = A[Lpos++];
		}
		else
		{
			TmpArray[TmpPos++] = A[Rpos++];
		}
	}

	while (Lpos <= LeftEnd)	 /* Copy rest of first half */
	{
		TmpArray[TmpPos++] = A[Lpos++];
	}
	while (Rpos <= RightEnd) /* Copy rest of second half */
	{
		TmpArray[TmpPos++] = A[Rpos++];
	}

	/* Copy TmpArray back */
	for (i = 0; i < NumElements; ++i, --RightEnd)
	{
		A[RightEnd] = TmpArray[RightEnd];
	}
}

void MSort(ElementType A[], ElementType TmpArray[], int Left, int Right)
{
	int Center;

	if (Left < Right)
	{
		Center = (Left + Right) / 2;
		MSort(A, TmpArray, Left, Center);
		MSort(A, TmpArray, Center + 1, Right);
		Merge(A, TmpArray, Left, Center + 1, Right);
	}
}

void MergeSort(ElementType A[], int N)
{
	ElementType *TmpArray;

	TmpArray = (ElementType *)malloc(N * sizeof(ElementType));
	if (TmpArray != NULL)
	{
		MSort(A, TmpArray, 0, N - 1);
		free(TmpArray);
	}
	else
	{
		FatalError("No space for tmp array!");
	}
}

/*-------------------QuickSort && QSelect---------------------------*/

/*
 * Return median of Left, Center, and Right.
 * Order these and hide the pivot.
 */
ElementType Median3(ElementType A[], int Left, int Right)
{
	int Center = (Left + Right) / 2;

	if (A[Left] > A[Center])
	{
		Swap(A + Left, A + Center);
	}
	if (A[Left] > A[Right])
	{
		Swap(A + Left, A + Right);
	}
	if (A[Center] > A[Right])
	{
		Swap(A + Center, A + Right);
	}

	/* Invariant: A[Left] <= A[Center] <= A[Right] */

	Swap(A + Center, A + Right - 1);	/* Hide pivot */
	return A[Right - 1];				/* Return pivot */
}

#define Cutoff (3)

void QSort(ElementType A[], int Left, int Right)
{
	int i, j;
	ElementType Pivot;

	if (Left + Cutoff <= Right)
	{
		/* Place the pivot in A[Right - 1] and initialize i and j to */
		/* Left + 1 and Right -2 */
		Pivot = Median3(A, Left, Right);
		i = Left;
		j = Right - 1;
		while (1)
		{
			while (A[++i] < Pivot) {}
			while (A[--j] > Pivot) {}
			if (i < j)
			{
				Swap(A + i, A + j);
			}
			else
			{
				break;
			}
		}
		Swap(A + i, A + Right - 1);		/* Restore pivot */

		QSort(A, Left, i - 1);
		QSort(A, i + 1, Right);
	}
	else	/* Do an insertion sort on the subarray */
	{
		InsertionSort(A + Left, Right - Left + 1);
	}
}

void QuickSort(ElementType A[], int N)
{
	QSort(A, 0, N - 1);
}

/*
 * Places the kth smallest element in the kth position.
 * Because arrays start at 0, this will be index k - 1.
 */
void QSelect(ElementType A[], int k, int Left, int Right)
{
	int i, j;
	ElementType Pivot;

	if (Left + Cutoff <= Right)
	{
		Pivot = Median3(A, Left, Right);
		i = Left; 
		j = Right - 1;
		for ( ; ;)
		{
			while (A[++i] < Pivot) { }
			while (A[--j] > Pivot) { }
			if (i < j)
			{
				Swap(&A[i], &A[j]);
			}
			else
			{
				break;
			}
		}
		Swap(&A[i], &A[Right - 1]);	/* Restore pivot */

		if (k <= i)
		{
			QSelect(A, k, Left, i - 1);
		}
		else if (k > i + 1)
		{
			QSelect(A, k, i + 1, Right);
		}
	}
	else
	{
		/* Do an insertion sort on the subarray */
		InsertionSort(A + Left, Right - Left + 1);
	}
}

/*-------------------RadixSort Inefficient------------------------*/

/*
 * Digit = Num / (Base ^ SpecifiedExponent) % Base
 */
int GetDigit(ElementType Num, int Base, int SpecifiedExponent)
{
	int i, Tmp;

	Tmp = 1;
	for (i = 0; i < SpecifiedExponent; ++i)
	{
		Tmp *= Base;
	}

	return (Num / Tmp % Base);
}

#define BASE (10)
#define MAX_EXPONENT (10)

/*
 * We assume elements in array A not bigger than 10 ^ 10.
 * And all elements is in base 10.
 */
void RadixSort(ElementType A[], int N)
{
	int i, j, k, Exponent, Digit;
	ElementType *Buckets[BASE];

	for (i = 0; i < BASE; ++i)
	{
		/* Alloc one more space for Count elements in Bucket */
		Buckets[i] = (ElementType *)malloc(sizeof(ElementType) * (N + 1));
		if (Buckets[i] == NULL)
		{
			FatalError("Out of space!");
		}
		Buckets[i][N] = 0;
	}

	/* BucketSort on the least significant digit, than two least significant digit, */
	/* until most significant digit */
	for (Exponent = 0; Exponent < MAX_EXPONENT; ++Exponent)
	{
		/* Place N elements in Buckets */
		for (i = 0; i < N; ++i)
		{
			Digit = GetDigit(A[i], BASE, Exponent);
			j = Buckets[Digit][N]++;
			Buckets[Digit][j] = A[i];
		}

		/* When all elements are placed in Buckets[0], terminated */
		if (Buckets[0][Digit] == N)
		{
			break;
		}

		/* Retrieve elements from Buckets(totally BASEs) orderly, into A[] */
		for (i = 0, k = 0; i < BASE; ++i)
		{
			for (j = 0; j < Buckets[i][N]; ++j)
			{
				A[k++] = Buckets[i][j];
			}

			/* Reset counter */
			Buckets[i][N] = 0;
		}
	}

	for (i = 0; i < BASE; ++i)
	{
		free(Buckets[i]);
	}
}
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值