C语言实现快排、归并排序、快排改进算法的递归和非递归算法

时间:2021-10-11 04:13:25

           其实以上算法的原理都很简单。在本科阶段,我们对这几个算法的基本原理都应该十分熟悉,但对于我,真正落实到是实现这几算法,之前几乎没有试过。现在刚上研一,算法课的第一次作业中,要求我们将这几个算法实现,对这几个算法,在输入规模不同的情况下,比较其实际工作效率。

          由于自己对算法具体的实现动手能力存在问题,就这几个算法的具体实现都花了我将近两天的时间。下面是源码:


这是定义的头文件:"h1.h"

#ifndef H1_H
#define H1_H
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <process.h>
#include <malloc.h>

#define SCALE 10000000

struct stackNode{  //快排非递归算法需要使用的栈节点
	int low;
	int high;
};

struct timeNode{ //时间节点
	long start;
	long end;
};


void quickSortRecursive(int a[], int n);
void qSort(int a[], int low, int high);
int partition(int a[], int low, int high); //以上三个函数是快排递归算法函数

void quickSortNoneRecursive(int a[], int n);//快排非递归算法函数

void mergeSortRecursive( int a[], int n);
void mSort(int a[], int low, int high);
void merge(int a[], int low, int center, int high);//归并排序递归算法函数预定义

void mergeSortNoneRecursive(int a[], int n);//归并排序非递归算法函数预定义

int randomNumber(int i, int j);   //用于快排改进算法在low和high之间产生随机数
void swap(int a[], int i, int j); //用于交换数组a中第i+1个和j+1个数

int modifiedPartition(int a[], int low, int high);//改进的partion函数
void modifiedQuickSortRecursive(int a[], int n);
void modifiedQSort(int a[], int low, int high);//改进的快排递归算法函数预定义

void modifiedQuickSortNoneRecursive(int a[], int n); //改进的快排非递归算法函数预定义
#endif

这里是这六个算法的具体实现文件: “sortAlgorithms.c”

#include "h1.h"

int partition(int a[], int low, int high){

	int temp = a[low];

	while(low < high){
		while(low<high && a[high]>=temp){
			high--;
		}
		a[low] = a[high];
		while(low<high && a[low]<=temp){
			low++;
		}
		a[high] = a[low];
	}
	a[low] = temp;
	return low;
}

void qSort(int a[], int low, int high){
	if( low < high){
		int pivotkey = partition( a, low, high );

		qSort( a, low, pivotkey-1 );
		qSort( a, pivotkey+1, high);
	}
}

void quickSortRecursive( int a[], int n){
	qSort( a, 0, n-1);
}
//快排递归算法

void quickSortNoneRecursive(int a[], int n){
	
	int i, j, low, high, temp;
	int top = 0;

	stackNode *st = (stackNode*) malloc(sizeof(stackNode)*SCALE);

	if( !st ){
		printf("内存分配故障!");
		exit(0);
	}

	st[top].low = 0;
	st[top].high = n-1;

	while( top > -1){
		low = st[top].low;
		high = st[top].high;
		top--;
		i = low;
		j = high;

		if( low < high ){
			temp = a[low];
			while( i < j){
				while(i<j && a[j]>=temp){
					j--;
				}
				a[i] = a[j];
				while(i<j && a[i]<=temp){
					i++;
				}
				a[j] = a[i];
			}
			a[i] = temp;

			if(i <= j){
				top++;
				st[top].low = low;
				st[top].high = i-1;
			
				top++;
				st[top].low = ++i;
				st[top].high = high;
			}
		}
	}
}
//快排非递归算法

void merge(int a[], int low, int center, int high){//这里的merge与教科书上有不同。我们用两个数组L[],R[]来存储a[]需要合并的两段
	                                               
	int i = 0;
	int j = 0;
	int k = 0;
	int count = 0;

	if(low >= high) return;

	int m = center - low + 1;
	int n = high - center;
	
	int *L = (int *)malloc(sizeof(int)*SCALE);
	int *R = (int *)malloc(sizeof(int)*SCALE);

	if(!L || !R){
		printf("归并排序merge()内存分配故障!");
		exit(0);
	}

	for( count=0; count<=m; count++){
		L[count] = a[low+count];
	}
	for( int count=0; count<=n; count++){
		R[count] = a[low+count+m];
	}

	for(i=0,j=0,k=low; i<m&&j<n; ++k){
		if( L[i] <= R[j] ){
			a[k] = L[i++];
		}
		else{
			a[k] = R[j++];
		}
	}

	while(i < m){
		a[k++] = L[i++];
	}
	while(j < n){
		a[k++] = R[j++];
	}
	free(L);
	free(R);
}

void mSort(int a[], int low, int high){
	
	int center;

	if(low < high){
		
		center = (low + high) / 2;
		mSort(a, low, center);
		mSort(a,  center+1, high);
		merge(a, low, center, high );
	}
}

void mergeSortRecursive(int a[], int n){
	mSort(a, 0, n-1);
}
//归并递归算法

void mergeSortNoneRecursive(int a[], int n){

	int t = 2;
	int i = 0;

	while( t <= (n-1)){
		i = 0;
		while((i+t-1) <= (n-1)){
			merge(a, i, i+t/2-1, i+t-1);
			i += t;
		}
		t *= 2;
	}
	merge(a, 0, t/2-1, n-1);
}
//归并非递归算法

int randomNumber(int i, int j){

	int	v = 0;

	if( i != j){
		v = rand()%(j-i) + i;
	}
	else{
		v = i;
	}
	return v;
}

void swap(int a[], int i, int j){

	int temp;
	temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}

int modifiedPartition(int a[], int low, int high){

	
	int pivot = randomNumber(low, high);
	int temp = a[pivot];

	while(low < high){
		while(low<high && a[high]>=temp){//这里的“=”必须加,因为当temp的值等于a[high]或a[low]时,不加等号,程序无法往继续执行,就会
			high--;                      //在两个相等值之间跳动无法继续执行
		}
		while(low<high && a[low]<=temp){
			low++;
		}
		swap(a, low, high);
	}
	a[low] = temp;
	return low; 
}


void modifiedQSort(int a[], int low, int high){
	
	if( low < high){
		int pivotkey = modifiedPartition( a, low, high );

		modifiedQSort( a, low, pivotkey-1 );
		modifiedQSort( a, pivotkey+1, high);
	}
}

void modifiedQuickSortRecursive(int a[], int n){
	
	modifiedQSort(a, 0, n-1);
}
// 改进后的快排递归算法

void modifiedQuickSortNoneRecursive(int a[], int n){

	int i, j, low, high, temp, pivotKey;
	int top = 0;
	stackNode *st = (stackNode*)malloc(sizeof(stackNode)*SCALE);

	st[top].low = 0;
	st[top].high = n-1;

	while(top > -1){
		
		low = st[top].low;
		high = st[top].high;
		top--;
		i = low;
		j = high;
		if(low < high){
			pivotKey = randomNumber(i, j);
			temp = a[pivotKey];
			while(i < j){
				while(i<j && a[j]>=temp){
					j--;
				}
				while(i<j && a[i]<=temp){
					i++;
				}
				swap(a, i, j);
			}
			a[i] = temp;
			if(i<=j){
					top++;
					st[top].low = low;
					st[top].high = i-1;

					top++;
					st[top].low = j+1;
					st[top].high = high;
			}
		}
	}

}
//改进后的快排非递归算法

主函数实现:"main.c"


#include "h1.h"

int main(){

	int i = 0;
	timeNode t[6];

	int *a = (int*)malloc(sizeof(int) * SCALE);

	if( !a ){
		printf("内存申请失败!");
		return 0;
	}
	for(i=0; i<SCALE; i++){
		a[i] = rand()%SCALE;
	}//产生将要进行排序的随机数
	
	for(int i=0; i<50; i++){
		printf("%d   ", a[i]);
	}

	
	t[0].start = clock();
	//quickSortRecursive( a, SCALE); //快排递归算法
	t[0].end = clock();

	t[1].start = clock();
	//quickSortNoneRecursive(a, SCALE);
	t[1].end = clock();

	t[2].start = clock();
	//mergeSortRecursive(a, SCALE);
	t[2].end = clock();

	t[3].start = clock();
	//mergeSortNoneRecursive(a, SCALE);
	t[3].end = clock();

	t[4].start = clock();
	//modifiedQuickSortRecursive(a, SCALE);
	t[4].end = clock();

	t[5].start = clock();
	modifiedQuickSortNoneRecursive(a, SCALE);
	t[5].end = clock();
	
	printf("\n");
	
	for(i=0; i<50; i++){
		printf("%d   ", a[i]);
	}

	printf("\n");

	for(i=0; i<6; i++){
		printf("%d 毫秒\n", (t[i].end-t[i].start));
	}
	return 0;
}