其实以上算法的原理都很简单。在本科阶段,我们对这几个算法的基本原理都应该十分熟悉,但对于我,真正落实到是实现这几算法,之前几乎没有试过。现在刚上研一,算法课的第一次作业中,要求我们将这几个算法实现,对这几个算法,在输入规模不同的情况下,比较其实际工作效率。
由于自己对算法具体的实现动手能力存在问题,就这几个算法的具体实现都花了我将近两天的时间。下面是源码:
这是定义的头文件:"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; }