版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wk_bjut_edu_cn/article/details/83868468
插入排序
#include<iostream>
using namespace std;
/*
插入排序的细节讲解与复杂度分析
时间复杂度O(N ^ 2),额外空间复杂度O(1)
*/
void InsertSort(int *arr, int length)
{
int i, j;
int temp;
if (arr == nullptr || length < 2)
return;
for (i = 1; i < length; ++i)
{
temp = arr[i];
j = i - 1;
while (j >= 0 && temp < arr[j])
{
arr[j + 1] = arr[j];
--j;
}
//找到插入位置,将temp中待排元素插入
arr[j + 1] = temp;
}
}
int main(void)
{
int arr[4] = { 4,3,2,1 };
InsertSort(arr, 4);
cout << arr[0] << arr[1] << arr[2] << arr[3] << endl;
system("pause");
return 0;
}
冒泡排序
#include<iostream>
using namespace std;
//将大的筛选筛选到后边
void BubbleSort(int *arr, int length)
{
if (arr == nullptr || length < 2)
return;
int flag;//标记
int temp;
for (int i = length - 1; i >= 1; --i)
{
flag = 0;//变量flag用来标记本趟排序是否发生了交换
for (int j = 1; j <= i; ++j)
{
if (arr[j - 1]>arr[j])
{
temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
//如果未发生交换,则flag的值为0;如果发生交换,则flag的值为1
flag = 1;
}
}
//一趟排序过程中没有发生元素交换,则证明序列有序,排序结束
if (flag == 0)
return;
}
}
int main(void)
{
int arr[2] = { 5,0 };
BubbleSort(arr, 2);
for (auto i : arr)
cout << i << " ";
cout << endl;
system("pause");
return 0;
}
快速排序(改进版)
#include<iostream>
#include<ctime>
using namespace std;
#define random(x)(rand()%x)
//快速排序
/*
在经典快排的基础上,做了两个改动
1.不是选择数组的最后一个数,而是随机选择一个
2.经典的是以一个数为中间,然后左边小于等于,右边大于
而现在是左边小于的数组,中间全部是等于这个数的数组,
右边是大于的数组
*/
void swap(int *arr, int i, int j);
int *partition(int *arr, int l, int r);
void QuickSort(int *arr, int l, int r)
{
if (l < r)
{
srand((int)time(0));
/*
经典快排是选择数组的最后一个数,现在改进的
随机快排多了随机选择数组中的一个数作为比较对象,
不一定非得是最后一个数
*/
swap(arr, random(r - l + 1)+l, r);
int *p = partition(arr, l, r);
QuickSort(arr, l, p[0] - 1);
QuickSort(arr, p[1] + 1, r);
}
}
int *partition(int *arr, int l, int r)
{
int less = l - 1;
int more = r;
while (l < more)
{
if (arr[l] < arr[r])
{
swap(arr, ++less, l++);
}
else if (arr[l]>arr[r])
{
swap(arr, --more, l);
}
else
{
l++;
}
}
//more是>=r的第一个位置,所以最后将r放到它该在的位置
swap(arr, more, r);//将最后一位作为比较的数移到它该在的位置
int *p = new int[2]{ less + 1,more };//遗留问题---------什么时候进行delete
return p;
}
void swap(int *arr, int i, int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
int main(void)
{
int i_arr[] = { 2,6,4,8,1,2,8,3};
QuickSort(i_arr, 0, 7);
for (int i : i_arr)
cout << i << " ";
cout << endl;
system("pause");
return 0;
}
简单选择排序
#include<iostream>
using namespace std;
void SelectSort(int *arr, int length)
{
int index, temp;
for (int i = 0; i < length - 1; ++i)
{
index = i;//当前的最小元素
//从无序数组中挑出一个最小的元素
for (int j = i + 1; j <= length - 1; ++j)
if (arr[j] < arr[index])
index = j;
//完成最小元素与无序序列中第一个元素的交换
temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
}
int main(void)
{
int arr[6] = { 6,5,4,3,2,1 };
SelectSort(arr, 6);
for (auto i : arr)
cout << i << " ";
cout << endl;
system("pause");
return 0;
}
堆排序
#include<iostream>
using namespace std;
/*
本函数完成对在arr[low]到arr[high]范围内对在位置
low上的节点进行调整
*/
void Sift(int *arr, int low, int high)
{
int i = low, j = 2 * i;
int temp = arr[i];
while (j <= high)
{
//右孩子存在且比左孩子大
if (j < high && arr[j] < arr[j + 1])
++j;
if (temp < arr[j])
{
arr[i] = arr[j];
i = j;
j = 2 * i;
}
else
break;
}
//被调整的节点的值找到了它该在的位置
arr[i] = temp;
}
//堆排序函数
void HeapSort(int *arr, int length)
{
int i;
int temp;
//建立初始堆
/*
因为要通过2*i求左右节点,所以数组的第一个元素不参与
*/
for (i = (length-1) / 2; i >= 1; --i)
Sift(arr, i, length - 1);
//每次都将最大元素放到数组的后面
for (i = length - 1; i >= 2; --i)
{
temp = arr[1];
arr[1] = arr[i];
arr[i] = temp;
//在减少了1个元素的无序序列中进行调整
Sift(arr, 1, i - 1);
}
}
int main(void)
{
int arr[6] = {-1,35,43,26,95,48};
HeapSort(arr, 6);
for (auto i : arr)
cout << i << " ";
cout << endl;
system("pause");
return 0;
}
二路归并排序
#include<iostream>
using namespace std;
/*
该函数实现的是合并两个有序子序列
*/
void Merge(int *arr, int low, int high, int mid)
{
int num1 = mid - low + 1;
int num2 = high - mid;
//将左半部分的有序子序列存到数组left中
int *left = new int[num1];
//将右半部分的有序子序列存到数组right中
int *right = new int[num2];
int i, j, k;
for (i = 0; i < num1; ++i)
left[i] = arr[low + i];
for (j = 0; j < num2; ++j)
right[j] = arr[mid + 1 + j];
//比较两个有序数组中的元素,每次都在找较小的元素
i = 0, j = 0, k = low;
while (i < num1 && j < num2)
{
if (left[i] < right[j])
arr[k++] = left[i++];
else
arr[k++] = right[j++];
}
//如果某个数组中还有元素,则把剩余部分全部拷入arr中,
//注意,不可能两个数组都还有元素
while (i < num1)
arr[k++] = left[i++];
while (j < num2)
arr[k++] = right[j++];
delete[]left;
delete[]right;
}
/*
二路归并排序
递归的方式进行,总是对两组有序数组进行排序
*/
void MergeSort(int *arr, int low, int high)
{
if (low < high)
{
int mid = (low + high) >> 1;
MergeSort(arr, low, mid);
MergeSort(arr, mid + 1, high);
Merge(arr, low, high, mid);
}
}
int main(void)
{
int arr[6] = {2,4,3,2,6,1};
MergeSort(arr, 0, 5);
for (auto i : arr)
cout << i << " ";
cout << endl;
system("pause");
return 0;
}
希尔排序
#include<iostream>
#include<vector>
using namespace std;
void print(const vector<int>& data);
void ShellInsert(vector<int>&data, int num)
{
for (int i = num; i < data.size(); ++i)
{
//说明需要进行调整,其实这部分就相当于是插入排序
if (data[i] < data[i - num])
{
int temp = data[i];
int j;
for (j = i - num; j >= 0 && temp < data[j]; j -= num)
data[j + num] = data[j];
data[j + num] = temp;
}
}
cout << "delta" << num << ":";
print(data);
cout << endl;
}
/*
data是待排序的数组
dalta是增量数组,可以由自己设定,一般5、3、1
*/
void ShellSort(vector<int>&data, vector<int>&delta)
{
for (int i = 0; i < delta.size(); ++i)
ShellInsert(data, delta[i]);
}
void print(const vector<int>& data)
{
for (auto i : data)
cout << i << " ";
}
int main(void)
{
vector<int> data{ 2,4,8,5,3,9,6 };
vector<int> delta{ 5,3,1 };
ShellSort(data, delta);
system("pause");
return 0;
}
基数排序
#include<iostream>
using namespace std;
/*
求一个数组中的元素的最大位数,以决定排序次数
*/
int MaxBit(int *data, int length)
{
int d = 1;//保存最大的位数
int p = 10;
for (int i = 0; i < length; ++i)
{
while (data[i] > p)
{
p *= 10;
++d;
}
}
//返回最大位数,比如数组中最大的元素是345,则返回的位数为3
return d;
}
//基数排序
void RadixSort(int *data, int length)
{
int d = MaxBit(data, length);
//从桶0-9,存放这些桶中的元素,相当于是已经排序依次以后的顺序
int *bucket = new int[length];
//桶中元素的计数器,count[0]表示第0个桶中存放的元素个数,依次类推
int *count = new int[10];
int i, j, k;
int radix = 1;
//最大位数是几,就要进行几次怕排序
for (i = 1; i <= d; ++i)
{
for (j = 0; j < 10; ++j)
count[j] = 0;//每次分配前都要清空计数器
for (j = 0; j < length; ++j)
{
k = (data[j] / radix) % 10;//统计每个桶中元素的个数,第一轮统计个位,第二轮十位,以此类推
count[k]++;//保存到计数器中
}
/*
这个是难点,在这卡了10分钟,count[i]表示第i个桶的右边界索引
*/
for (j = 1; j < 10; ++j)
count[j] += count[j - 1];
//从后向前放,比如个位数相同,后出现的在后面放,保持了稳定性
//bucket数组中的数就是这一轮排序之后的依次呈现
for (j = length - 1; j >= 0; --j)
{
k = (data[j] / radix) % 10;
bucket[count[k] - 1] = data[j];
count[k]--;
}
//基数排序的收集,把桶中的数据再倒出来,然后进行前一位数的排序
for (j = 0; j < length ; ++j)
data[j] = bucket[j];
for (int y = 0; y < length; ++y)
cout << data[y] << " ";
cout << endl;
radix *= 10;
}
delete[]bucket;
delete[]count;
}
int main(void)
{
int arr[5] = { 2,567,238,904,123};
RadixSort(arr, 5);
for (auto i : arr)
cout << i << " ";
cout << endl;
system("pause");
return 0;
}
排序算法分析
n为元素的个数,d为关键字的位数,rd为桶数。