个人根据网上资源,总结的几个排序算法,并且用c++实现。
1,main.cpp
#include <iostream>
#include "api_sort.h"
#include "common.h"
using namespace std;
#define NEW_ARRAY 0
int main()
{
#if NEW_ARRAY
int len=0 ;
cout<<"请输入数组长度:"<<endl;
cin>>len;
int *arr=new int[len];
cout<<"请输入长度为:"<<len<<"的待排序的数组:"<<endl;
for (int i=0;i<len;i++){
cin>>*(arr+i); //获取输入
}
#endif // NEW_ARRAY
int len = 10;
int arr[] = {10,6,5,2,3,8,7,4,9,1};
//int arr[] = {50,26,38,80,70,90,8,30,40,20};
/*打印数组*/
cout<<"待排序的数组为:"<<endl;
printArray(arr,len);
/*
################################
#1.插入排序算法
################################
*/
/*1.1.1 直接插入排序*/
//directInsertSort(arr,len);
/*1.1.2 交换插入排序*/
//swapInsertSort(arr,len);
/*1.1.3 二分法插入排序*/
//bSearchInsertSort(arr,len);
/*1.2 希尔排序*/
//shellInsertSort(arr,len);
/*
################################
#2.交换排序算法
################################
*/
/*2.1.1 冒泡排序*/
// bubbleSort(arr,len);
/*2.1.2 冒泡排序改进-鸡尾酒排序*/
// cocktailSort(arr,len);
/*2.2快速排序*/
// quitSort(arr,0,len-1);
// printArray(arr,len);
/*
################################
#3.选择排序算法
################################
*/
/*3.1选择排序*/
//selectSort(arr,len);
/*3.2堆排序*/
heapSort(arr,len);
#if NEW_ARRAY
delete[] arr;
#endif // NEW_ARRAY
return 0;
}
2,api_sort.h
/*
################################
#1.插入排序算法
################################
*/
//1.1.1直接插入排序
/*
将待排序的无序数列看成是一个仅含有一个元素的有序数列和一个无序数列,
将无序数列中的元素逐次插入到有序数列中,从而获得最终的有序数列。
*/
void directInsertSort(int* p, int len);
//1.1.2插入排序改进-交换
/*
用数据交换代替法1.1.1的数据后移(比较对象只考虑两个元素)
*/
void swapInsertSort(int* p, int len);
//1.1。3插入排序改进-二分法查找
/*
先折半查找到插入位置,再统一移动元素
*/
void bSearchInsertSort(int* p, int len);
//1.2 希尔排序
/*
希尔排序是第一个突破O(n2)的排序算法,是简单插入排序的优化,
实质是分组的简单插入排序。它与插入排序的不同之处在于,
它会优先比较距离较远的元素(每次取相隔一定间隔gap的元素作为一组,
在组内执行简单插入排序)。希尔排序又叫缩小增量排序(不断减小间隔gap的数组,直到gap=1)。
*/
void shellInsertSort(int* p, int len);
/*
################################
#2.交换排序算法
################################
*/
//2.1.1 冒泡排序
void bubbleSort(int* p, int len);
/*2.1.2 冒泡排序改进-鸡尾酒排序*/
/*
与冒泡排序的不同处在于排序时是以首尾双向在序列中进行排序
*/
void cocktailSort(int* p, int len);
//2.2 快速排序
/*
快速排序是目前所有内部排序算法中平均性能最优的排序算法。
i=L,j=R,将基准数挖出形成第一个坑a[i];
j−−由后向前找出比它小的数,找到后挖出此数a[j]填到前一个坑a[i]中;
i++从前向后找出比它大的数,找到后也挖出此数填到前一个坑a[j]中;
再重复2,3,直到i=j,将基准数填到a[i]。
*/
void quitSort(int* p, int low,int hight);
/*
################################
#3.选择排序算法
################################
*/
//3.1 简单选择排序
/*
在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;
然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,
依次类推,直到第n−1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
*/
void selectSort(int* p, int len);
//3.2 堆排序
/*
堆排序(HeapSort)是指利用堆这种数据结构所设计的一种排序算法。
堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:
即子结点的键值或索引总是小于(或者大于)它的父节点。
性质一:索引为i的左孩子的索引是 (2∗i+1);
性质二:索引为i的右孩子的索引是 (2∗i+2);
*/
void heapSort(int* p, int len);
void HeapSort(int array[],int heapSize);
3. api_sort.cpp
#include <iostream>
#include "common.h"
using namespace std;
///
//1.插入排序算法
//
//1.1.1直接插入排序
void directInsertSort(int* p, int len){
int i,j,temp=0;
for( i = 1;i<len;i++){
temp = *(p+i);
for( j=i-1;j>=0 && *(p+j)>temp;j--){
*(p+j+1) = *(p+j);
}
*(p+j+1)=temp;
cout<<"第"<<i<<"次排序后结果:";
printArray(p,len);
}
};
//1.1.2插入排序改进-交换
void swapInsertSort(int* p, int len){
int i,j,temp=0;
for(i=1; i<len; i++){
temp=*(p+i);
for(j=i-1;j>=0 && *(p+j)>temp; j--){
swap(&p[j+1],&p[j]);
}
cout<<"第"<<i<<"次排序后结果:";
printArray(p,len);
}
};
//1.1.3插入排序改进-二分法查找
void bSearchInsertSort(int* p, int len){
int i,j;
for(i=1;i<len;i++){
int low=0;
int high=i-1;
int temp=p[i];
while(low<=high){
int mid=(low+high)/2;
if(p[mid]>temp){
high=mid-1;
}else{
low=mid+1;
}
}
for(j=i-1;j>=low;j--){
p[j+1]=p[j];
}
p[j+1]=temp;
cout<<"第"<<i<<"次排序后结果:";
printArray(p,len);
}
};
//1.2 希尔排序
void shellInsertSort(int* p, int len){
int i,j,temp,gap;
int count=0;
for(gap=len/2;gap>0;gap/=2){
for(i=gap;i<len;i+=gap){
temp=p[i];
for(j=i-gap;j>=0 && p[j]>temp ;j-=gap){
swap(&p[j],&p[j+gap]);
// p[j+gap]=p[j];
}
// p[j+gap]=temp;
count++;
cout<<"gap="<<gap<<" 第"<<count<<"次排序后结果:";
printArray(p,len);
}
}
};
///
//2. 交换排序算法
//
//2.1.1冒泡排序
void bubbleSort(int* p, int len){
int count=0;
for(int i=0;i<len-1;i++){
for(int j=i+1;j<len;j++){
if(p[i]>p[j]){
swap(&p[i],&p[j]);
}
count++;
cout<<"第"<<count<<"次排序后结果:";
printArray(p,len);
}
}
}
/*2.1.2 冒泡排序改进-鸡尾酒排序*/
void cocktailSort(int* p, int len){
int count=0;
int left=0;
int right=len-1;
while(left<right){
/*先对数组从左到右进行升序的冒泡排序,大的放最右边*/
for(int i=left;i<right;i++){
if(p[i]>p[i+1]){
swap(&p[i],&p[i+1]);
}
}
right--;
/*再对数组进行从右到左的降序的冒泡排序,小的放最左边*/
for(int j=right;j>left;j--){
if(p[j]<p[j-1]){
swap(&p[j],&p[j-1]);
}
}
left++;
count++;
cout<<"第"<<count<<"次排序后结果:";
printArray(p,len);
}
}
/*2.2 快速排序*/
void quitSort(int* p, int low,int high){
if(low<high){
int left=low;
int right=high;
int base=p[left];
while(left<right){
while(left<right && p[right]>=base){
right--;
}
if(left<right)
p[left++]=p[right];
while(left<right && p[left]<base){
left++;
}
if(left<right)
p[right--]=p[left];
}
p[left]=base;
quitSort(p,low,left-1);
quitSort(p,left+1,high);
}
}
//3.1 简单选择排序
void selectSort(int* p, int len){
int i=0;
int cur=0;
while(cur<len-1){
int pos=cur;
for(i=cur;i<len-1;i++){
if(p[i+1]<p[pos]){
pos=i+1;
}
}
if(pos!=cur){
swap(&p[pos],&p[cur]);
cout<<"第"<<cur<<"次排序后结果:";
printArray(p,len);
}
cur++;
}
}
//3.2 堆排序
void adjustMaxHeap(int a[], int len, int parentNodeIndex) {
// 若只有一个元素,那么只能是堆顶元素,也没有必要再排序了
if (len <= 1) {
return;
}
// 记录比父节点大的左孩子或者右孩子的索引
int targetIndex = -1;
// 获取左、右孩子的索引
int leftChildIndex = 2 * parentNodeIndex + 1;
int rightChildIndex = 2 * parentNodeIndex + 2;
// 没有左孩子
if (leftChildIndex >= len) {
return;
}
// 有左孩子,但是没有右孩子
if (rightChildIndex >= len) {
targetIndex = leftChildIndex;
}
// 有左孩子和右孩子
else {
// 取左、右孩子两者中最大的一个
targetIndex = a[leftChildIndex] > a[rightChildIndex] ? leftChildIndex : rightChildIndex;
}
// 只有孩子比父节点的值还要大,才需要交换
if (a[targetIndex] > a[parentNodeIndex]) {
int temp = a[targetIndex];
a[targetIndex] = a[parentNodeIndex];
a[parentNodeIndex] = temp;
// 交换完成后,有可能会导致a[targetIndex]结点所形成的子树不满足堆的条件,
// 若不满足堆的条件,则调整之使之也成为堆
adjustMaxHeap(a, len, targetIndex);
}
}
// 初始化堆
void initHeap(int a[], int len) {
// 从完全二叉树最后一个非子节点开始
// 在数组中第一个元素的索引是0
// 第n个元素的左孩子为2n+1,右孩子为2n+2,
// 最后一个非子节点位置在(n - 1) / 2
for (int i = (len - 1) / 2; i >= 0; --i) {
adjustMaxHeap(a, len, i);
}
}
void heapSort(int a[], int len) {
if (len <= 1) {
return;
}
// 初始堆成无序最大堆
initHeap(a, len);
for (int i = len - 1; i > 0; --i) {
// 将当前堆顶元素与最后一个元素交换,保证这一趟所查找到的堆顶元素与最后一个元素交换
// 注意:这里所说的最后不是a[len - 1],而是每一趟的范围中最后一个元素
// 为什么要加上>0判断?每次不是说堆顶一定是最大值吗?没错,每一趟调整后,堆顶是最大值的
// 但是,由于len的范围不断地缩小,导致某些特殊的序列出现异常
// 比如说,5, 3, 8, 6, 4序列,当调整i=1时,已经调整为3,4,5,6,8序列,已经有序了
// 但是导致了a[i]与a[0]交换,由于变成了4,3,5,6,8反而变成无序了!
if (a[0] > a[i]) {
int temp = a[0];
a[0] = a[i];
a[i] = temp;
}
// 范围变成为:
// 0...len-1
// 0...len-1-1
// 0...1 // 结束
// 其中,0是堆顶,每次都是找出在指定的范围内比堆顶还大的元素,然后与堆顶元素交换
adjustMaxHeap(a, i - 1, 0);
cout<<"第"<<i<<"次排序后结果:";
printArray(a,len);
}
}
4, common.cpp
#include <iostream>
using namespace std;
void printArray(int* p,int len){
for (int i=0;i<len;i++){
cout<< *(p+i)<<"\t";
}
cout<<endl<<endl;
}
void swap(int* a, int* b){
int temp=*a;
*a=*b;
*b=temp;
};