// 排序算法1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
using namespace std;
void SelectSort(int Arr[], int size);//选择排序
void InsertSort(int Arr[], int size);//插入排序
void ShellSort(int Arr[], int size);//希尔排序
void CountSort(int Arr[], int size);//计数排序
void RadixSort(int Arr[], int size);//基数排序
void QuickSort(int Arr[], int left, int right);//快速排序
void MergeSort(int Arr[], int size);//归并排序
void _MergeSort(int intArr[], int l, int r);//拆分
void mergeArr(int* intArr, int l, int m, int r);//合并
void swap(int& num1, int& num2);
void Display(int Arr[], int size);
int NumofBitofArr(int iArr[], int size);//求最大的位数
int _tmain(int argc, _TCHAR* argv[])
{
int Arr[] = { 23, 45,12, 7, 9,26,10,5, 319,18 };
int size = sizeof(Arr) / sizeof(int);
/*选择排序
从头至尾扫描序列,找出最小的一个元素,和第一个元素交换,接着从剩下的元素中继续这种选择和交换方式,
最终得到一个有序序列。
*/
/*插入排序
每一步将一个待排序的数据插入到前面已经排好序的有序序列中,直到插完所有元素为止
*/
//SelectSort(Arr, size);
//Display(Arr, size);
/*InsertSort(Arr, size);*/
//ShellSort(Arr, size);
/*CountSort(Arr, size);*/
/*QuickSort(Arr, 0, size-1);*/
MergeSort(Arr, size);
Display(Arr, size);
return 0;
}
/*
选择排序(Selection-sort)是一种简单直观的排序算法。
它的工作原理:首先在未排序序列中找到最小(大)元素
,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,
然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
*/
void SelectSort(int Arr[],int size)
{
for (int i = 0; i < size-1; i++)//遍历数组下标 从0开始
{
int index = i;
for (int j = i+1; j < size; j++)
{
if (Arr[index]>Arr[j])
{
index = j;//下标交换
}
}
if (i != index)
{
swap(Arr[i], Arr[index]);//数字交换
}
}
}
/*
插入排序算法是一种简单直观的排序算法。
它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
*/
void InsertSort(int Arr[], int size)
{
int temp = 0;
int j = 0;
for (int i = 1; i < size; i++)//插入排序认为第一个元素天然有序,从第二个元素开始
{
temp = Arr[i];
j = i - 1;//已排序中最大的一个
while (j>=0&&Arr[j]>temp)//当已排序中的最大元素大于数组中的元素的时候
{
Arr[j + 1] = Arr[j];//数字交换
j--;
}
Arr[j + 1] = temp;
}
}
/*
它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
*/
void ShellSort(int Arr[], int size)
{
int step = size / 2;//步长
int temp = 0;//定义一个临时变量
while (step>0)
{
for (int i = step; i < size; i++)//插入排序
{
temp = Arr[i];
int j = i - step;
while (j>=0 && Arr[j]>temp)
{
Arr[j + step] = Arr[j];
j = j - step;
}
Arr[j + step] = temp;
}
Display(Arr, size);
step /= 2;
}
}
/*
计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。
作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
步骤:
找出待排序的数组中最大和最小的元素;
统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。
*/
void CountSort(int Arr[], int size)
{
int maxNum = Arr[0];
for (int i = 1; i < size; i++)//找出数组中最大值
{
if (Arr[i]>maxNum)
{
maxNum = Arr[i];
}
}
int *pTmpArr = new int[maxNum + 1];//创建计数数组,长度为maxNum+1
memset(pTmpArr, 0x00, sizeof(int)*(maxNum + 1));
for (int i = 0; i < size; i++)//遍历原数组的元素
{
pTmpArr[Arr[i]]++; //对计数数组元素赋值,统计出现的次数
}
int index = 0;//下标
for (int i = 0; i < maxNum; i++)//从最小的数开始计数,遍历计数数组
{
for (int j = 0; j < pTmpArr[i]; j++)//将计数数组的索引值填充到数组中
{
Arr[index++] = i;
}
}
delete[]pTmpArr;
}
/*
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,
先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
*/
void RadixSort(int Arr[], int size)//基数排序
{
int nBits = NumofBitofArr(Arr, size);//求数组中最大的位数
int nCount[10] = { 0 };//定义10个桶0~9
int *pTempArr = new int[size];//定义一个临时数组
memset(pTempArr, 0x00, sizeof(int)*size);//数组中的元素为0
int radix = 1;
for (int i = 0; i <= nBits; i++)//统计循环的次数。。也就是说百位就循环2次,千位就循环3次
{
memset(nCount, 0x00, sizeof(nCount));//清空桶
for (int j = 0; j < size; j++)
{
nCount[Arr[j] / radix % 10]++;//取个位、十位.....对应的数字取出来
}
// 比如经过计算后 0, 2, 3, 3, 0, 0, 0, 0, 表示0出现了0次,1出现了2次等等,则 0,2, 5, 8, 0, 0, 。。。
//2表示比较位为1的元素可以存放在索引为1, 0的位置
//5表示比较位为2的元素可以存放在4,3,2 3个位置上(5- 2)
//8表示比较位为3的元素可以存在7,6,5 3个位置上(8 - 5)
for (int i = 1; i < 10; i++)
{
nCount[i] = nCount[i] + nCount[i - 1];
}
for (int j = size-1; j >= 0; j--)//在桶中从个位开始,从下到上依次取出
{
int k = Arr[j] / radix % 10;
pTempArr[nCount[k] - 1] = Arr[j];
nCount[k]--;
}
for (int j = 0; j < size; j++)//重新放在桶中
{
Arr[j] = pTempArr[j];
}
Display(Arr, size);
radix *= 10;
}
}
int NumofBitofArr(int iArr[], int size)//求最大的位数
{
int nBits = 1;//位数
int temp = 10;
for (int i = 0; i < size; i++)//遍历数组中每一个数
{
while (iArr[i] >= temp)
{
temp *= 10;
nBits++;
}
}
return nBits;
}
/*
从数列中挑出一个元素,称为 “基准”(pivot);
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
*/
void QuickSort(int Arr[], int left, int right)
{
if (left>=right)
return;//退出条件
int Middle = Arr[left];//基准值
int l = left;//比中间值小的在左边
int r = right;//比中间值大的在右边
while (l!=r)
{
while (l<r && Arr[r]>=Middle)//首先从数组右边开始扫描,当扫描的值大于等于基准值
r--;//右边减
if (l < r)//当小于基准值
Arr[l] = Arr[r];//就将右边的元素值给左边
while (l<r && Arr[l]<=Middle) //接着从左边开始扫描,当值小于等于基准值
l++;//左边加
if (l<r)
Arr[r] = Arr[l];//进行数据交换
}
Arr[l] = Middle;//将基准值赋予左边
cout << Middle << "为基准" << endl;
Display(Arr, 10);
//采用递归的方式,对于左右2边分别进行快速排序
QuickSort(Arr, left, l - 1); //左边
QuickSort(Arr, l + 1, right); //右边
}
/*
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
*/
void MergeSort(int Arr[], int size)
{
int r = size - 1;
_MergeSort(Arr, 0, r);
}
void _MergeSort(int Arr[], int l,int r)
{
if (l>=r)
{
return;
}
int mid = l + (r - l) / 2;//中间值
_MergeSort(Arr, l, mid);//拆分左边
_MergeSort(Arr, mid + 1, r);//拆分右边
mergeArr(Arr, l, mid, r);
}
void mergeArr(int *Arr, int l, int m, int r)
{
int left = l;//左边
int right = m+1;//右边第一个元素
int size = r - l + 1;//2个数组的总长度
int *tempArr = new int[size];
int index = 0;//合并数组的开始位置
while (left<m && right<=r)//这里结束的条件是一个数组已经放进去了
{
if (Arr[left]<Arr[right])//开始位置比较,如果左边数组元素小于右边数组,则将左边数组放进去,然后位置加1
{
tempArr[index++] = Arr[left++];
}
else//否则相反
{
tempArr[index++] = Arr[right++];
}
}
while (left<=m)//如果left没有放完就直接放在最后面
{
tempArr[index++] = Arr[left++];
}
while (right<=r)//如果right没有放完就直接放在最后面
{
tempArr[index++] = Arr[right++];
}
memcpy(Arr + l, tempArr, sizeof(int)*size);
}
void swap(int& num1, int& num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void Display(int Arr[], int size)
{
for (int i = 0; i < size; i++)
{
cout << Arr[i] << "\t";
}
cout << endl;
}
7种典型的排序算法-代码及原理说明
最新推荐文章于 2025-12-26 16:39:46 发布
本文详细介绍了多种排序算法的实现,包括选择排序、插入排序、希尔排序、计数排序、快速排序、归并排序,并提供了相应的代码示例。通过这些排序算法的实现,读者可以深入理解它们的工作原理和效率。
271

被折叠的 条评论
为什么被折叠?



