#include<iostream>
using namespace std;
/***************
* 直接插入排序
*算法性能:
*稳定
*空间代价:Θ(1)
*时间代价:
*最佳情况:n-1次比较,2(n-1)次移动,Θ(n)
*最差情况: Θ(n2)
***************/
void InsertSort(int *a,int n);
/*****************
* 折半插入排序
*****************/
void BinaryInsertSort(int *a ,int n);
/******************************************************
* 折半与直接插入排序都是稳定的,时间复杂度都是n^2
******************************************************/
void display(int *a,int n);
/*****************
*希尔排序
*算法性能:
*不稳定
*空间代价:Θ(1)
*增量每次除以2递减,时间代价:Θ(n2)
*选择适当的增量序列,可以使得时间代价接近Θ(n)
*******************/
void ShellInsert(int* pDataArray, int d, int iDataNum);
void ShellSort(int* pDataArray, int iDataNum);
/********************************************
*冒泡排序,稳定的排序
********************************************/
void BubbleSort(int *a,int n);
//void BubbleSort(int Array[], int n);
/*******************************************
*快速排序
*性能分析
*最差情况:
*时间代价: Θ(n2)
*空间代价: Θ(n)
*最佳情况:
*时间代价:Θ(nlog n)
*空间代价:Θ(log n)
*平均情况:
*时间代价:Θ(nlog n)
*空间代价:Θ(log n)
*******************************************/
void quickSort(int a[],int left,int right);
void quickSort2(int a[],int left,int right);
/*******************************************
*直接选择排序
*性能分析:
*不稳定
*空间代价:O(1)
*时间代价:比较次数O(n^2),交换次数n-1,总时间代价O(n^2)
*******************************************/
void selectSort(int *a,int n);
/******************************************
*堆排序
*算法性能:
*建堆:Θ(n)
*删除堆顶重新建:Θ(log n)
*一次建堆,n次删除堆顶
*总时间代价为Θ(nlog n)
*空间代价为Θ(1
*******************************************/
void heapSort(int *a,int n);
/*****************************
*归并排序
*算法性能
*稳定
*空间代价:Θ(n)
*总时间代价:Θ(nlog n)
*不依赖于原始数组的输入情况,
*最大、最小以及平均时间代价均为Θ(nlog n)
*****************************/
void mergeSort(int *a,int start,int end);
int main(){
int a[8] = {2,1,4,6,3,5,4,7};
//InsertSort(a,8);
//BinaryInsertSort(a,8);
//ShellSort(a,8);
//BubbleSort(a,8);
//quickSort2(a,0,7);
//selectSort(a,8);
//heapSort(a,8);
mergeSort(a,0,7);
display(a,8);
return 0;
}
//直接插入排序
void InsertSort(int *a,int n){
int temp=0;
int j=0;
int i;
for( i=1;i<n;i++){
j=i-1;
temp = a[i];
while((j>=0)&&(a[j]>temp)){
a[j+1] = a[j];
j--;
}
a[j+1] = temp;
}
}
//输出函数
void display(int *a ,int n){
int i;
for(i=0;i<n;i++){
cout<<a[i]<<" ";
}
}
//折半插入排序
void BinaryInsertSort(int *a,int n){
int temp,i,j,left,right,middle;
for(i=1;i<n;i++){
temp = a[i];
left = 0;
right = i-1;
while(left<=right){ //必须要有“=”
middle = (left+right)/2;
if(a[i]>a[middle]){
left = middle + 1 ;
}
else{
right = middle - 1;
}
}
for(j=i-1;j>=left;j--){ //必须要有“=”
a[j+1] = a[j];
}
a[left] = temp;
}
}
/********************************************************
*函数名称:ShellInsert
*参数说明:pDataArray 无序数组;
* d 增量大小
* iDataNum为无序数据个数
*说明: 希尔按增量d的插入排序
*********************************************************/
void ShellInsert(int* pDataArray, int d, int iDataNum)
{
for (int i = d; i < iDataNum; i += d) //从第2个数据开始插入
{
int j = i - d;
int temp = pDataArray[i]; //记录要插入的数据
while (j >= 0 && pDataArray[j] > temp) //从后向前,找到比其小的数的位置
{
pDataArray[j+d] = pDataArray[j]; //向后挪动
j -= d;
}
if (j != i - d) //存在比其小的数
pDataArray[j+d] = temp;
}
}
/********************************************************
*函数名称:ShellSort
*参数说明:pDataArray 无序数组;
* iDataNum为无序数据个数
*说明: 希尔排序
*********************************************************/
void ShellSort(int* pDataArray, int iDataNum)
{
int d = iDataNum / 2; //初始增量设为数组长度的一半
while(d >= 1)
{
ShellInsert(pDataArray, d, iDataNum);
d = d / 2; //每次增量变为上次的二分之一
}
}
/****************************
*冒泡排序
****************************/
void BubbleSort(int *a,int n){
int i,j,temp;
bool flag;//用于记录是否发生交换的标志
for(i=0;i<n-1;i++){
flag = true;
for(j = 1;j<n-i;j++){
if(a[j]<a[j-1]){
temp = a[j];
a[j] = a[j-1];
a[j-1] = temp;
flag = false;//如果有一趟没有发生交换的话,证明整个排序已经完成就不用在进行下面的冒泡
}
}
if(flag)
return ;
}
}
/********************************************************
*快速排序 分割算法1,返回轴值的记录
********************************************************/
int Partition1(int a[],int left ,int right){
//实现对从a[left],到a[right]的分割操作,并返回划分后轴元素的位置
int pivot = a[left]; //选取第一个元素作为轴元素
while(left < right){
while(left<right&&a[right]>pivot){ //从右边开始找到一个小于轴元素的位置
right --;
}
a[left] = a[right]; //将right位置上的数据放到left(原轴元素)的位置上
while(left<right&&a[left]<=pivot){ /*******等号不能省去***/
left ++;
}
a[right] = a[left]; //将left位置上的元素移动到right位置上, 此时left位置空出
}
a[left] = pivot;
return left; //返回轴元素的位置,实现分治
}
int Partition2(int a[],int start,int end){
int pivot = a[start];
int temp;
int left = start,right = end;
while(left<=right){
while(left<=right&&a[left]<=pivot){
left++;
}
while(left<=right&&a[right]>pivot){
right --;
}
if(left<right){
temp = a[left];
a[left] = a[right];
a[right] = temp;
left ++;
right --;
}
}
//cout<<left<<"***"<<right<<endl;
/*****交换轴元素与right位置的值*****/
temp =a[right];
a[right] = a[start];
a[start] = temp;
return right;
}
void quickSort(int a[],int left,int right){
if(left<right){
int p = Partition1(a,left,right);
quickSort(a,left,p-1);
quickSort(a,p+1,right);
}
}
void quickSort2(int a[],int left,int right){
if(left<right){
int p = Partition2(a,left,right);
quickSort2(a,left,p-1);
quickSort2(a,p+1,right);
}
}
/*******************************************
*直接选择排序
*******************************************/
void selectSort(int *a,int n){
int small,i,j;
for(i=0;i<n;i++){
small = i; //假设最小的值就是i位置上的值
for(j=i+1;j<n;j++){
if(a[j]<a[small]){
// 如果发现更小的记录,记录它的位置
small = j;
}
}
if(small!=i){
//当发现i位置的值不是最小的时候则进行交换
int temp = a[i];
a[i] = a[small];
a[small] = temp;
}
}
}
/******************************
*堆排序
******************************/
void siftDown(int *a,int i ,int n){
int leftChild = 2*i+1;
int rightChild = 2*i+2;
int minRoot = i;
if(n>leftChild&&a[minRoot]<a[leftChild]){
minRoot = leftChild;
}
if(n>rightChild&&a[minRoot]<a[rightChild]){
minRoot = rightChild;
}
if(minRoot!=i){//当根节点不是最小值的时候
int temp = a[i];
a[i] = a[minRoot];
a[minRoot] = temp;
siftDown(a,minRoot,n);//递归对子节点进行调整
}
}
void buildHeap(int *a,int n){
int p = n/2 -1;//记录非叶子节点的最大下标,因为叶子节点不用进行调整
for(int i=p;i>=0;i--){
siftDown(a,i,n);
}
}
void heapSort(int *a ,int n){
buildHeap(a,n);//构建最大堆
for(int i = n-1;i>0;i--){
int temp = a[i]; //将堆顶的值跟最后一个值进行交换,这是该元素就被放在了正确的位置上
a[i] = a[0];
a[0] = temp;
siftDown(a,0,i);
}
}
/**************归并排序*********************/
//合并一个序列中的两个有序子序列
void Merge(int *a,int start,int mid,int end){
// cout<<"s:"<<start<<" "<<"m:"<<mid<<" "<<"e:"<<end<<endl;
int len1 = mid - start +1 ;
int len2 = end - mid +1 ;
int i;
int j;
int k;
//临时数组存放a[start,mid]和a[mid+1,end]的值
int * left = new int[len1];
int * right = new int[len2];
for(i=0;i<len1;i++){
left[i] = a[i+start];
}
for(i=0;i<len2;i++){
right[i] = a[i+mid+1];
}
//合并left,right
i = 0; j = 0; k = 0;
for(k = start;k<end;k++){
if(i==len1||j==len2){
break;
}
if(left[i]<=right[j]){
a[k] = left[i];
i++;
}else{
a[k] = right[j];
j++;
}
}
while(i<len1){
a[k] = left[i];
k++;
i++;
}
while(j<len2){
a[k] = right[j];
k++;
j++;
}
delete[] left;
delete[] right;
}
void mergeSort(int *a,int start,int end){
//cout<<"start:"<<start<<" "<<"end:"<<end<<endl;
if(start<end){
int mid = (start+end)/2;
// cout<<"start:"<<start<<" "<<"end:"<<end<<endl;
// cout<<"left"<<" "<<"mid:"<<mid<<"end:"<<end<<endl;
mergeSort(a,start,mid);
// cout<<"right"<<" "<<"mid:"<<mid<<"end:"<<end<<endl;
mergeSort(a,mid+1,end);
Merge(a,start,mid,end);
}
}
常用排序算法总结与分析(含全部源码)
最新推荐文章于 2021-03-13 19:03:42 发布