You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
303 lines
9.0 KiB
303 lines
9.0 KiB
#include<iostream>
|
|
using namespace std;
|
|
|
|
int len = 10;
|
|
int a[10] = {5,7,2,6,4,1,3,9,8,10};
|
|
|
|
/*
|
|
*冒泡排序,时间复杂度O(N^2);空间复杂度:O(1);稳定排序
|
|
*思路:第一趟:两两元素相比,前一个比后一个大就交换,直到将最大的元素交换到末尾位置;一共进行n-1趟这样的交换将可以把所有的元素排好。
|
|
*/
|
|
void MaoPao(int a[]){
|
|
int temp;
|
|
int flag = 0;
|
|
// n-1趟排序
|
|
for(int i = 0; i < len - 1; i++){
|
|
for(int j = 0; j < len - 1 -i; j++){
|
|
if(a[j] > a[j + 1]){
|
|
temp = a[j];
|
|
a[j] = a[j + 1];
|
|
a[j + 1] = temp;
|
|
flag = 1;
|
|
}
|
|
}
|
|
// 若某一趟排序中没有元素交换则说明所有元素已经有序,不需要再排序
|
|
if(flag == 0)break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*插入排序,时间复杂度O(N^2);空间复杂度O(1);稳定排序
|
|
*思路:假设数组除最后一个元素都有序了,那么将最后一个元素与前面的比较,如果前面的元素大则向右移动。实际过程从数组的第二个元素开始执行插入排序
|
|
*/
|
|
void ChaRu(int a[]){
|
|
// 从第一轮就从第二个元素开始找,所以n-1轮就可以
|
|
for(int i = 0; i < len - 1; i++){
|
|
// 已经有序的最后一个元素
|
|
int end = i;
|
|
// 需要排序的元素
|
|
int temp = a[end + 1];
|
|
while(end >= 0){
|
|
if(a[end] > temp){
|
|
// 直接替换 循环外面再将被替换的值放到适当位置
|
|
a[end + 1] = a[end];
|
|
end--;
|
|
}
|
|
else{
|
|
break;
|
|
}
|
|
}
|
|
a[end + 1] = temp;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*希尔排序,时间复杂度O(N^1.5);空间复杂度O(1);不稳定排序。
|
|
*思路:先选定一个整数gap,把待排序文件中所有记录分成gap个组,所有距离为gap的记录分在同一组内,并对每一组内的元素进行排序。然后将gap逐渐减小重复上述分组和排序的工作。当到达gap=1时,所有元素在统一组内排好序。
|
|
*/
|
|
void ShellSort(int a[], int n){
|
|
int gap = n;
|
|
while (gap > 1)
|
|
{
|
|
//gap /= 2;
|
|
gap = gap / 3 + 1;
|
|
for (int i = 0; i < n - gap; i++)
|
|
{
|
|
int end = i;
|
|
int x = a[end + gap];
|
|
while (end >= 0)
|
|
{
|
|
if (a[end] > x)
|
|
{
|
|
a[end + gap] = a[end];
|
|
end -= gap;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
a[end + gap] = x;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*选择排序,时间复杂度O(N^2); 空间复杂度O(1);不稳定排序。
|
|
*思路:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始(末尾)位置,然后选出次小(或次大)的一个元素,存放在最大(最小)元素的下一个位置,重复这样的步骤直到全部待排序的数据元素排完。优化:每次最大和最小同时选.
|
|
*/
|
|
void SelectSort(int a[], int n){
|
|
//保存数组的起始位置
|
|
int begin = 0;
|
|
//保存换数组的末尾位置
|
|
int end = n - 1;
|
|
int temp;
|
|
while (begin < end)
|
|
{
|
|
int maxi = begin;//保存最大元素下标
|
|
int mini = begin;//保存最小元素下标
|
|
//遍历数组寻找最小和最大元素
|
|
for (int i = begin; i <= end; i++)
|
|
{
|
|
if (a[i] < a[mini])
|
|
{
|
|
mini = i;
|
|
}
|
|
if (a[i] > a[maxi])
|
|
{
|
|
maxi = i;
|
|
}
|
|
}
|
|
//将最小元素交换到起始位置
|
|
temp = a[begin];
|
|
a[begin] = a[mini];
|
|
a[mini] = temp;
|
|
|
|
//判断最大值的位置是否在起始位置
|
|
if (maxi == begin)
|
|
{
|
|
maxi = mini;
|
|
}
|
|
//将最大元素交换到末尾位置
|
|
temp = a[end];
|
|
a[end] = a[maxi];
|
|
a[maxi] = temp;
|
|
//移动数组起始和末尾位置
|
|
begin++;
|
|
end--;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*堆排序,时间复杂度O(N*logN);空间复杂度O(1);不稳定排序。
|
|
*思路:升序为例,构建一个堆结构,然后每个父节点均替换为子节点的最大值,然后根节点就是最大值,重复这个步骤。
|
|
*/
|
|
void HeapAdjust(int H[], int s, int length)
|
|
{
|
|
int tmp = H[s];
|
|
// 左孩子结点的位置。(i+1 为当前调整结点的右孩子结点的位置)
|
|
int child = 2 * s + 1;
|
|
while (child < length)
|
|
{
|
|
if (child + 1 < length && H[child] < H[child + 1])
|
|
{ // 如果右孩子大于左孩子(找到比当前待调整结点大的孩子结点)
|
|
child++;
|
|
}
|
|
if (H[s] < H[child])
|
|
{ // 如果较大的子结点大于父结点
|
|
H[s] = H[child]; // 那么把较大的子结点往上移动,替换它的父结点
|
|
s = child; // 重新设置s ,即待调整的下一个结点的位置
|
|
child = 2 * s + 1;
|
|
}
|
|
else
|
|
{ // 如果当前待调整结点大于它的左右孩子,则不需要调整,直接退出
|
|
break;
|
|
}
|
|
H[s] = tmp; // 当前待调整的结点放到比其大的孩子结点位置上
|
|
}
|
|
}
|
|
/**
|
|
* 初始堆进行调整
|
|
* 将H[0..length-1]建成堆
|
|
* 调整完之后第一个元素是序列的最小的元素
|
|
*/
|
|
void BuildingHeap(int H[], int length)
|
|
{
|
|
// 最后一个有孩子的节点的位置 i= (length -1) / 2
|
|
for (int i = (length - 1) / 2; i >= 0; --i)
|
|
HeapAdjust(H, i, length);
|
|
}
|
|
void HeapSort(int H[], int length)
|
|
{
|
|
// 初始堆
|
|
BuildingHeap(H, length);
|
|
// 从最后一个元素开始对序列进行调整
|
|
for (int i = length - 1; i > 0; --i)
|
|
{
|
|
// 交换堆顶元素H[0]和堆中最后一个元素
|
|
int temp = H[i];
|
|
H[i] = H[0];
|
|
H[0] = temp;
|
|
// 每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整
|
|
HeapAdjust(H, 0, i);
|
|
}
|
|
}
|
|
|
|
/*
|
|
*快速排序,时间复杂度O(N*logN);空间复杂度O(logN);不稳定排序。
|
|
*思路:最右边的值为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。确定两个指针left 和right 分别从左边和右边向中间遍历数组。如果选最右边为基准值,那么left指针先走,如果遇到大于基准值的数就停下来。然后右边的指针再走,遇到小于基准值的数就停下来。交换left和right指针对应位置的值。重复以上步骤,直到left = right ,最后将基准值与left(right)位置的值交换。
|
|
*/
|
|
int PartSort(int a[], int left, int right){
|
|
// 选最右面为基准
|
|
int key = right;
|
|
while(left < right){
|
|
//选右边为基准值,左指针先走
|
|
while(left < right && a[left] <= a[key]){
|
|
left++;
|
|
}
|
|
//右指针再走
|
|
while(left < right && a[right] >= a[key]){
|
|
right--;
|
|
}
|
|
// 交换
|
|
int temp = a[right];
|
|
a[right] = a[left];
|
|
a[left] = temp;
|
|
}
|
|
int temp = a[key];
|
|
a[key] = a[left];
|
|
a[left] = temp;
|
|
return left;
|
|
}
|
|
void QuickSort(int a[], int left, int right){
|
|
if(left >= right)return;
|
|
// 第一次快排
|
|
int keyi = PartSort(a, left, right);
|
|
// 左子序列快排
|
|
QuickSort(a, left, keyi - 1);
|
|
// 右子序列快排
|
|
QuickSort(a, keyi + 1, right);
|
|
}
|
|
|
|
/*
|
|
*归并排序,递归实现,时间复杂度O(N*logN);空间复杂度O(N);稳定排序。
|
|
*思路:采用分治法,将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
|
|
*/
|
|
void _MergeSort(int* a, int left, int right,int* tmp)
|
|
{
|
|
//区间中没有元素时不再合并
|
|
if (left >= right)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//划分数组,每次一分为二
|
|
int mid = (left + right) / 2;
|
|
_MergeSort(a, left, mid,tmp);//划分左区间
|
|
_MergeSort(a, mid + 1, right,tmp);//划分右区间
|
|
|
|
//合并有序序列
|
|
int begin1 = left, end1 = mid;//有序序列1
|
|
int begin2 = mid + 1, end2 = right;//有序序列2
|
|
int i = left;
|
|
//注意结束条件为一个序列为空时就停止
|
|
while (begin1 <= end1 && begin2 <= end2)
|
|
{
|
|
if (a[begin1] < a[begin2])
|
|
{
|
|
tmp[i++] = a[begin1++];
|
|
}
|
|
else
|
|
{
|
|
tmp[i++] = a[begin2++];
|
|
}
|
|
}
|
|
|
|
//两序列不可能同时为空,将剩余元素合并
|
|
while (begin1 <= end1)
|
|
{
|
|
tmp[i++] = a[begin1++];
|
|
}
|
|
|
|
while (begin2 <= end2)
|
|
{
|
|
tmp[i++] = a[begin2++];
|
|
}
|
|
|
|
//将合并后的序列拷贝到原数组中
|
|
//在这里拷贝的原因是 保证返回到上一层递归后两个子序列中的元素是有序的
|
|
int j = 0;
|
|
for (j = left; j <= right; j++)
|
|
{
|
|
a[j] = tmp[j];
|
|
}
|
|
}
|
|
void MergeSort(int* a, int n)
|
|
{
|
|
//因为需要将两个有序序列合并,需借助额外数组
|
|
int* tmp = (int*)malloc(sizeof(int) * n);
|
|
if (tmp == NULL)
|
|
{
|
|
perror("malloc");
|
|
exit(-1);
|
|
}
|
|
_MergeSort(a, 0, n - 1,tmp);
|
|
free(tmp);
|
|
tmp = NULL;
|
|
}
|
|
|
|
int main(){
|
|
|
|
// MaoPao(a);
|
|
// ChaRu(a);
|
|
// ShellSort(a, len);
|
|
// SelectSort(a, len);
|
|
// HeapSort(a, len);
|
|
// QuickSort(a, 0, len - 1);
|
|
// MergeSort(a, len);
|
|
cout<<"out:"<<endl;
|
|
for(int i = 0; i < len; i++){
|
|
cout<<a[i];
|
|
cout<<',';
|
|
}
|
|
}
|