七大排序
不废话,直接上代码,注释分明,思路清晰。
sortingmethod.h
#ifndef SORTINGMETHOD_H
#define SORTINGMETHOD_H
#include <iostream>
#define SORTTYPE int
using namespace std;
/**
* insert sort
*/
/*direct insert sort*/
void direct_insert_sort( SORTTYPE *arr,int len);
/*shell sort*/
void shell_sort(SORTTYPE *arr,int len);
/**
* select sort
*/
/*simple select sort*/
void simple_select_sort( SORTTYPE *arr ,int len);
/*heap sort*/
void heap_sort(SORTTYPE *arr,int len);
void adjust_max_heap(SORTTYPE *arr, int len,int i);
void build_max_heap(SORTTYPE *arr , int len);
/**
* exchange sort
*/
/*bubble sort*/
void bubble_sort( SORTTYPE *arr ,int len);
/*fast sort*/
void quick_sort(SORTTYPE *arr , int start, int end);
/**
* merge sort
*/
void merge_merge_sort(SORTTYPE *arr , int first, int mid ,int last , SORTTYPE *temp);
void devide_merge_sort(SORTTYPE *arr , int first, int last , SORTTYPE *temp);
void merge_sort(SORTTYPE *arr, int len);
/*show element*/
void show_element(SORTTYPE *arr , int len);
#endif // SORTINGMETHOD_H
sortingmethod.cpp
#include "sortingmethod.h"
/*
* All sorting is from min to max
*/
/**
* insert sort
*/
/*direct insert sort*/
void direct_insert_sort( SORTTYPE *arr,int len){
int temp ,i=0,j=0; /*temp暂存arr[i]*/
for(i = 1 ; i < len ; i++){
/*对每一个arr[i]~arr[0]的数*/
temp = arr[i];
for(j=i ; j>0 ; j -- ) {
/*当arr[j-1]比tem大时,向右移动一个位置*/
if ( arr[j-1] > temp ){
arr[j] = arr[j-1];
}
else
break;
}
/*此时j刚好为重复的那个数字*/
arr[j] = temp;
}
// for(i = 1; i<len ; i++){
// temp = arr[i];
// for(j = i-1 ; j > -1 ; j--){
// if(arr[j]>temp){
// arr[j+1] = arr [j];
// }
// else
// break;
// }
// arr[j+1] = temp;
// }
}
/*shell sort*/
void shell_sort(SORTTYPE *arr,int len){
/*
* 将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;
* 每次将gap折半减小,循环上述操作;
* 当gap=1时,利用直接插入,完成排序。
*/
int i=0,j=0,k=-1,temp=-1;
int gap = len / 2; /*初始化gap,一般时len的一半*/
while( gap >= 1 ){
for( i = gap ; i < len ; i+=gap ){
k = i; temp = arr[k];
for( j = i - gap ; (j >= 0)&&(arr[j] >temp); j -=gap ){
arr[j+gap] = arr[j];
k = j;
}
arr[k] = temp;
}
gap /=2;
}
}
/**
* select sort
*/
/*simple select sort*/
void simple_select_sort( SORTTYPE *arr ,int len){
/*
简单选择排序的基本思想:比较+交换。
从待排序序列中,找到关键字最小的元素;
如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;
从余下的 len - 1 个元素中,找出关键字最小的元素,重复(1)、(2)步,直到排序结束。
因此简单选择排序也是通过两层循环实现。
第一层循环:依次遍历序列中的每一个元素
第二层循环:将遍历得到的当前元素依次与余下的元素进行比较,符合最小元素的条件,则交换。
*/
int i=0,j=0,k=0,min,tem;
for(i=0; i < len ; i++ ){
min = arr[i];
/*下面这个循环找到本轮的最小值和下标*/
for(j = i+1 ; j < len ; j++){
if(arr[j] < min){
min = arr[j];
k = j;
}
}
/*如果arr[i]>min则需要交换*/
if(arr[i] > min){
tem= arr[i];
arr[i] = arr[k];
arr[k] = tem;
}
}
}
/*heap sort*/
/*
堆排序按照以下步骤完成:
1.首先将序列构建称为大顶堆;
(这样满足了大顶堆那条性质:位于根节点的元素一定是当前序列的最大值
2.取出当前大顶堆的根节点,将其与序列末尾元素进行交换;
(此时:序列末尾的元素为已排序的最大值;由于交换了元素,当前位于根节点的堆并不一定满足大顶堆的性质)
3.对交换后的n-1个序列元素进行调整,使其满足大顶堆的性质;
4.重复2.3步骤,直至堆中只有1个元素为止
*/
/* 调整大顶堆 */
void adjust_max_heap(SORTTYPE *arr, int len,int i){
/*
* arr:待调整序列
* len: 序列长度
* i:需要调整的结点
*/
/*定义一个int值保存当前序列最大值的下标*/
int largest = i; int left,right;
/*执行循环操作任务:1.寻找最大值的下标;2.最大值与父节点交换*/
while (1) {
/*获得序列左右叶子节点的下标*/
left = i*2+1; right = i*2+2;
/*当左叶子节点的下标小于序列长度 并且 左叶子节点的值大于父节点时,将左叶子节点的下标赋值给largest*/
if(left < len && arr[left] > arr[largest]){
largest = left;
}else{
largest = i;
}
/*当右叶子节点的下标小于序列长度 并且 右叶子节点的值大于父节点时,将右叶子节点的下标值赋值给largest*/
if(right < len && arr[right] > arr[largest])
largest = right;
/*如果largest不等于i 说明当前的父节点不是最大值,需要交换值*/
int temp;
if(largest != i){
temp = arr[i];
arr[i] = arr[largest];
arr[largest] = temp;
i = largest;
continue;
}else{
break;
}
}
}
/*建立大顶堆*/
void build_max_heap(SORTTYPE *arr , int len){
for( int i = (len-1)/2; i>-1; i-- ){
adjust_max_heap(arr,len,i);
}
}
/* 堆排序 heap_sort */
void heap_sort(SORTTYPE *arr,int len){
/*先建立大顶堆,保证最大值位于根节点;并且父节点的值大于叶子结点*/
build_max_heap(arr , len);
/* i = 当前堆中序列的长度.初始化为序列的长度*/
int i = len;
/*执行循环:1. 每次取出堆顶元素置于序列的最后(len-1,len-2,len-3...)
2. 调整堆,使其继续满足大顶堆的性质,注意实时修改堆中序列的长度*/
int temp;
while( i > 0){
temp = arr[i-1];
arr[i - 1] = arr[0];
arr[0] = temp;
/*堆中序列长度减1*/
i-=1;
/*调整大顶堆*/
adjust_max_heap(arr , i , 0);
}
}
/**
* exchange sort
*/
/*bubble sort*/
void bubble_sort( SORTTYPE *arr ,int len){
int temp;
for(int i =0 ; i < len ; i++ ){
for(int j = len-1; j>i ; j --){
if (arr[j] < arr[j-1]){
temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp;
}
}
}
}
/*quick sort*/
void quick_sort(SORTTYPE *arr ,int start,int end){
/*快速排序的基本思想:挖坑填数+分治法
从序列当中选择一个基准数(pivot ,这里选择序列当中第一个数最为基准数)
将序列当中的所有数依次遍历,比基准数大的位于其右侧,比基准数小的位于其左侧
重复步骤1.2,直到所有子集当中只有一个元素为止。
用伪代码描述如下:
1.i =left; j = right; 将基准数挖出形成第一个坑a[i]。
2.j--由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。
3.i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。
4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中
*/
int i, j ,pivot;
if (start <end){
i = start;
j = end;
pivot = arr[start];
}
else
return; /*注意这个地方容易忘*/
while(i < j){
/*从右开始向左寻找第一个小于pivot的值*/
while(i < j && arr[j] >= pivot)
j-=1;
/*将小于pivot的值移到左边*/
if(i < j){
arr[i] = arr[j];
i+=1;
}
/*从左开始向右寻找第一个大于pivot的值*/
while (i < j && arr[i] <= pivot)
i+=1;
/*将大于pivot的值移到右边*/
if(i<j){
arr[j] = arr[i];
j-=1;
}
}
/*循环结束后,说明 i=j,此时左边的值全都小于pivot,右边的值全都大于pivot*/
arr[i]=pivot;
show_element(arr,14);
/*pivot的位置移动正确,那么此时只需对左右两侧的序列调用此函数进一步排序即可*/
/*递归调用函数:依次对左侧序列:从0 ~ i-1//右侧序列:从i+1 ~ end*/
quick_sort(arr,start,i-1);
cout<<"left is all right"<<endl;
quick_sort(arr,i+1,end);
}
/**
* merge sort
*/
/*
* merge_sort
* 归并排序的函数
*/
void merge_sort(SORTTYPE *arr,int len){
/*
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个典型的应用。
它的基本操作是:
将已有的子序列合并,达到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
归并排序要做两件事:
分解----将序列每次折半拆分
合并----将划分后的序列段两两排序合并
因此,归并排序实际上就是两个操作,拆分+合并
如何合并?
arr[first...mid]为第一段,arr[mid+1...last]为第二段,并且两端已经有序,现在要将两端合成达到arr[first...last]并且也有序。
(1)依次从第一段与第二段中取出元素比较,将较小的元素赋值给temp[]
(2)重复执行上一步,当某一段赋值结束,则将另一段剩下的元素赋值给temp[]
(3)此时将temp[]中的元素复制给arr[],则得到的arr[first...last]有序
如何分解?
(1)采用递归的方法,首先将待排序列分成A,B两组;
(2)重复对A、B序列分组;
(3)直到分组后组内只有一个元素,此时认为组内所有元素有序,分组结束。
*/
SORTTYPE temp[len];
/*调用归并排序*/
devide_merge_sort(arr, 0 , len-1 , temp);
}
void merge_merge_sort(SORTTYPE *arr , int first, int mid , int last , int *temp){
/*合并的函数----将序列arr[first...mid]与序列arr[mid+1...last]进行合并*/
int i = first, j = mid +1 ,k = 0;
/*当左右两边都有数时进行比较,取较小的数*/
while(i <= mid && j <= last){
if( arr[i] <= arr[j])
temp[k++] = arr[i++];
else
temp[k++] = arr[j++];
}
/*如果左边序列还有数*/
while(i <= mid)
temp[k++] = arr[i++];
/*如果右边序列还有数*/
while(j <= last)
temp[k++] = arr[j++];
/*将temp当中该段有序元素赋值给L待排序列使之部分有序*/
for(int x = 0; x < k ; x++)
arr[first + x] = temp[x];
}
/*这是分组的函数*/
void devide_merge_sort(SORTTYPE *arr , int first, int last , SORTTYPE *temp){
int mid;
if(first < last){
mid = (first + last)/2;
/*使左边序列有序*/
devide_merge_sort(arr, first ,mid ,temp);
/*使右边序列有序*/
devide_merge_sort(arr, mid+1 , last ,temp);
/*将两个有序序列合并*/
merge_merge_sort(arr, first ,mid , last,temp);
show_element(arr , 14);
}
}
/*show element*/
void show_element(SORTTYPE *arr , int len){
for(int i = 0; i < len ; i++ ){
SORTTYPE tem = arr[i];
cout<<tem<<" ";
}
cout<<'\n';
}
main.cpp
#include <iostream>
#include "sortingmethod.h"
using namespace std;
int main()
{
SORTTYPE arr[] = {8,1,13,7,3,12,4,6,2,14,5,9,11,10};
int len = 14;
show_element(arr, len);
// direct_insert_sort(arr,len);
// bubble_sort(arr , len);
// shell_sort(arr,len);
// simple_select_sort(arr,len);
// heap_sort(arr , len);
// quick_sort(arr,0,13);
// merge_sort(arr,len);
cout<<"sort ending!"<<endl;
show_element(arr, len);
return 0;
}