/*****/排序

直接插入排序

插入排序的基本思想是:
每次将一个待排的记录,按照其关键字的大小,插入到前面已经排好序的有序区中适当的位置,直到全部记录插入完毕为止。
假设待排序的记录存放在数组R[0..n]中,初始时R[0]是一个有序区,R[1..n]是无序区,从i=1开始,依次将R[i]插入到有序区R[0..i-1]中,生成一个包含n个记录的有序区。

这里写图片描述

Sort.h

#pragma once
void PrintArray(int *a, size_t n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << "";
    }
    cout << endl;//换行
}
void InsertSort(int *a, size_t n)
{
    assert(a);
    for (size_t i = 0; i < n - 1; ++i)
    {
        int end = i;
        int tmp = a[end + 1];
        while (end >= 0)
        {
            if (a[end]>tmp)
            {
                a[end + 1] = a[end];
                    --end;
            }
            else
            {
                break;
            }
        }
        a[end + 1] = tmp;
    }
}
void TestInsertSort()
{
    int a[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
    PrintArray(a, sizeof(a) / sizeof(a[0]));
    InsertSort(a, sizeof(a) / sizeof(a[0]));
    PrintArray(a, sizeof(a) / sizeof(a[0]));
}

Test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include"Sort.h"
int main()
{
    TestInsertSort();
    return 0;
}

这里写图片描述

SHELL排序

希尔排序又称为缩小增量排序,它是插入排序的一种变形。

希尔排序:
设待排序元素有n个,首先取一个整数gap

#pragma once
void PrintArray(int *a, size_t n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << "";
    }
    cout << endl;//换行
}
void ShellSort(int *a, size_t n)
{
    assert(a);
    int gap = n;
    while (gap > 1)
    {
        gap = gap / 3 + 1;
        for (size_t i= 0; i < n - gap; ++i)
        {
            int end = i;
            int tmp = a[end + gap];
            while (end >= 0)
            {
                if (a[end]>tmp)
                {
                    a[end + gap] = a[end];
                    end -= gap;
                }
                else
                    break;
            }
            a[end + gap] = tmp;

        }
    }

}
void TestShellSort()
{
    int a[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
    PrintArray(a, sizeof(a) / sizeof(a[0]));
    ShellSort(a, sizeof(a) / sizeof(a[0]));
    PrintArray(a, sizeof(a) / sizeof(a[0]));
}

Test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include"Sort.h"
int main()
{
    TestShellSort();
    return 0;
}

这里写图片描述

选择排序

选择排序的基本思想:初始时,有序区为0,每一趟在无序区中选出一个关键字最小的元素,然后与无序区第一个元素交换,然后无序区减1,有序区加1,直到记录全部排完。
直接选择排序:第一趟排序在R[0..n]中选出一个关键字最小的与R[0]交换,第二趟在R[1..n]中选择一个最小的与R[1]进行交换,以此类推直到无序区的记录只剩一个时排序完成。

这里写图片描述

Sort.h

#pragma once
void PrintArray(int *a, size_t n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << "";
    }
    cout << endl;//换行
}
void SelectSort(int *a, size_t n)
{
    assert(a);
    size_t left = 0, right = n - 1;
    while (left < right)
    {
        size_t min = left, max = left;
        for (size_t i = left; i <= right; ++i)
        {
            if (a[min]>a[i])
                min = i;
            if (a[max] < a[i])
                max = i;
        }
        //修正
        swap(a[min], a[left]);
        if (max == left)
            max = min;
        swap(a[max], a[right]);
        ++left; --right;
    }

}
void TestSelectSort()
{
    int a[] = { 9, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
    PrintArray(a, sizeof(a) / sizeof(a[0]));
    SelectSort(a, sizeof(a) / sizeof(a[0]));
    PrintArray(a, sizeof(a) / sizeof(a[0]));
}

Test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include"Sort.h"
int main()
{
    TestSelectSort();
    return 0;
}

这里写图片描述

堆排序

时间复杂度: 第一次建堆的时间复杂度:O(N*lgN)。 每次调整的时间复杂度是O(lgN),总共有N次,即:O(N*lgN); 所以:
堆排序的时间复度:O(N*lgN)

Sort.h

#pragma once
void PrintArray(int *a, size_t n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << "";
    }
    cout << endl;//换行
}
void AdjustDown(int *a, size_t root, size_t n)
{
    size_t parent = root;
    size_t child = parent * 2 + 1;
    while (child < n)
    {
        if (child + 1 < n && a[child + 1] > a[child])
        {
            ++child;
        }
        if (a[child]>a[parent])
        {
            swap(a[child], a[parent]);
            parent = child;
            child = 2 * parent + 1;
        }
    }
}
void HeapSort(int *a,size_t n)
{
    assert(a);
    for (int i = (n - 2) / 2; i >= 0; --i)
    {
        AdjustDown(a, i, n);
    }
    size_t end = n - 1;
    while (end > 0)
    {
        swap(a[0], a[end]);
        AdjustDown(a, 0, end);
    }
}
void TestHeapSort()
{
    int a[] = { 9, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
    PrintArray(a, sizeof(a) / sizeof(a[0]));
    HeapSort(a, sizeof(a) / sizeof(a[0]));
    PrintArray(a, sizeof(a) / sizeof(a[0]));
}

Test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include"Sort.h"
int main()
{
    TestHeapSort();
    return 0;
}

冒泡排序
Sort.h

#pragma once
void PrintArray(int *a, size_t n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << "";
    }
    cout << endl;//换行
}
void BubbleSort(int *a, size_t n)
{
    assert(a);
    int end = n;
    while (end > 0)
    {
        bool exchange = false;
        for (int i = 1; i < end; ++i)
        {
            if (a[i - 1]>a[i])
            {
                swap(a[i - 1], a[i]);
                exchange = true;
            }
        }
        if (exchange == false)
        {
            break;
        }
        --end;
    }
}
void TestBubbleSort()
{
    int a[] = { 1,2,3,4,5,7,6 };
    PrintArray(a, sizeof(a) / sizeof(a[0]));
    BubbleSort(a, sizeof(a) / sizeof(a[0]));
    PrintArray(a, sizeof(a) / sizeof(a[0]));
}

Test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include"Sort.h"
int main()
{
    TestBubbleSort();
    return 0;
}

这里写图片描述

快速排序是一种划分交换的方法,它采用分治法进行排序。其基本思想是取待排序元素序列中的某个元素作为基准值,按照这个元素的大小,将整个元素序列划分成两个左右两个子序列,使得左子序列的值都比这个元素小,右子序列中的值都比这个元素值要大于或等于,基准元素值则排在这两个序列中间,然后再对这两个子序列进行同样的方法,直到所有元素都排在相应的位置(即序列中只有一个元素或者没有元素的时候)。
这里写图片描述
快速排序方法一

左右指针法

Sort.h

#pragma once
void PrintArray(int *a, size_t n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << "";
    }
    cout << endl;//换行
}
//快速排序左右指针法
int PartSort1(int *a, int left, int right)
{
    int key = a[right];
    int begin = left;
    int end = right;
    while (begin < end)
    {
        while (begin < end && a[begin] <= key)
        {
            ++begin;
        }
        while (begin < end && a[end] >= key)
        {
            --end;
        }
        if (begin < end)
            swap(a[begin], a[end]);
    }
    swap(a[begin], a[right]);
        return begin;

}

void QuickSort(int *a, int left, int right)
{
    assert(a);
    if (left < right)
    {
        int div = PartSort1(a, left, right);
        QuickSort(a, left, div - 1);
        QuickSort(a, div + 1, right);
    }
}
void TestQuickSort()
{
    int a[] = { 5,0,4,9,3,6,5,7,1,5};
    PrintArray(a, sizeof(a) / sizeof(a[0]));
    QuickSort(a,0, sizeof(a) / sizeof(a[0]) - 1);
    PrintArray(a, sizeof(a) / sizeof(a[0]));
}

Test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include"Sort.h"
int main()
{
    TestQuickSort();
    return 0;
}

这里写图片描述

换个测试用例试试:
这里写图片描述

快速排序方法二

挖坑法

Sort.h

#pragma once
void PrintArray(int *a, size_t n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << "";
    }
    cout << endl;//换行
}
//快速排序之挖坑法
int PartSort2(int *a, int left, int right)
{
    int key = a[right];
    while (left < right)
    {
        //找大
        while (left < right && a[left] <= key)
        {
            ++left;
        }
        //找到比key大的数放到右边的坑里,左边形成新的坑
        a[right] = a[left];
        while (left < right && a[right] >= key)
        {
            --right;
        }
        a[left] = a[right];
    }
    a[left] = key;
    return left;
}

void QuickSort(int *a, int left, int right)
{
    assert(a);
    if (left < right)
    {
        int div = PartSort2(a, left, right);
        QuickSort(a, left, div - 1);
        QuickSort(a, div + 1, right);
    }
}
void TestQuickSort()
{
    int a[] = { 5,0,4,9,3,6,5,7,1,5};
    PrintArray(a, sizeof(a) / sizeof(a[0]));
    QuickSort(a,0, sizeof(a) / sizeof(a[0]) - 1);
    PrintArray(a, sizeof(a) / sizeof(a[0]));
}

Test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include"Sort.h"
int main()
{
    TestQuickSort();
    return 0;
}

这里写图片描述

快速排序方法三

前后指针法
Sort.h

#pragma once
void PrintArray(int *a, size_t n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << "";
    }
    cout << endl;//换行
}
//快速排序之前后指针法
int PartSort3(int *a, int left, int right)
{
    int prev = left - 1;
    int cur = left;
    int key = a[right];
    while (cur < right)
    {
        if (a[cur] < key &&  ++prev != cur)
        {
            swap(a[prev], a[cur]);
        }
        ++cur;
    }
    swap(a[++prev], a[right]);
    return prev;
}

void QuickSort(int *a, int left, int right)
{
    assert(a);
    if (left < right)
    {
        int div = PartSort3(a, left, right);
        QuickSort(a, left, div - 1);
        QuickSort(a, div + 1, right);
    }
}
void TestQuickSort()
{
    int a[] = { 5,0,4,9,3,6,5,7,1,5};
    PrintArray(a, sizeof(a) / sizeof(a[0]));
    QuickSort(a,0, sizeof(a) / sizeof(a[0]) - 1);
    PrintArray(a, sizeof(a) / sizeof(a[0]));
}

Test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include"Sort.h"
int main()
{
    TestQuickSort();
    return 0;
}

这里写图片描述

快排的最坏情况:有序 (解决:三数取中)
用第一种方法示例:
Sort.h

#pragma once
void PrintArray(int *a, size_t n)
{
    for (size_t i = 0; i < n; ++i)
    {
        cout << a[i] << "";
    }
    cout << endl;//换行
}
int GetMidIndex(int*a, int left, int right)
{
    int mid = left + (right - left) / 2;
    //left mid right
    if (a[left] < a[mid])
    {
        if (a[mid] < a[right])
        {
            return mid;
        }
        else if (a[left]>a[right])
        {
            return left;
        }
        else
        {
            return right;
        }
    }

    else //left>min right
    {
        if (a[mid] > a[right])
            return mid;
        else
        if (a[left] < a[right])
            return left;
        else
            return right;
    }


}

int PartSort1(int *a, int left, int right)
{
    //三数取中
    int mid = GetMidIndex(a, left, right);
    swap(a[mid], a[right]);
    int key = a[right];
    int begin = left;
    int end = right; //防止有序排成无序
    while (begin < end)
    {
        while (begin < end && a[begin] <= key)
        {
            ++begin;
        }
        while (begin < end && a[end] >= key)
        {
            --end;
        }
        if (begin < end)
            swap(a[begin], a[end]);
    }
    swap(a[begin], a[right]);
    return begin;

}
void QuickSort(int *a, int left, int right)
{
    assert(a);
    if (left < right)
    {
        int div = PartSort1(a, left, right);
        QuickSort(a, left, div - 1);
        QuickSort(a, div + 1, right);
    }
}
void TestQuickSort()
{
    int a[] = { 5,0,4,9,3,6,5,7,1,5};
    PrintArray(a, sizeof(a) / sizeof(a[0]));
    QuickSort(a,0, sizeof(a) / sizeof(a[0]) - 1);
    PrintArray(a, sizeof(a) / sizeof(a[0]));
}

Test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include"Sort.h"
int main()
{
    TestQuickSort();
    return 0;
}

快速排序非递归

//快速排序非递归
#include<stack>
void QuickSortNonR(int *a, int left, int right)
{
    assert(a);
    stack<int> s;
    if (left < right)
    {
        s.push(right);
        s.push(left);
    }
    while (!s.empty())
    {
        int begin = s.top();
        s.pop();
        int end = s.top();
        s.pop();

        int div = PartSort1(a, begin, end);
        //begin div-1
        //div+1 end
        if (begin < div - 1)
        {
            s.push(div - 1);
            s.push(begin);
        }
        if (div + 1 < end)
        {
            s.push(end);
            s.push(div + 1);
        }
    }
}

归并排序

归并排序是一种基于分治法的一种排序方法。它将要排序的序列分成两个长度相等的子序列,为每一个子序列进行排序,然后再将子序列合并成一个有序的序列。

这里写图片描述

void _MergeSort(int *a,int begin,int end,int *tmp)  
{  
       int mid = ((begin^end) >> 1) + (begin&end);  
       if (mid > begin)  
              _MergeSort(a,begin,mid,tmp);  
       if (mid + 1 < end)  
              _MergeSort(a,mid+1,end,tmp);  
       int begin1 = begin;  
       int end1 = mid;  
       int begin2 = mid + 1;  
       int end2 = end;  
       int index = begin;  
       while(begin1<=end1&&begin2<=end2)             //先将归并时的元素放到辅助数组中,如果放到原数组的话有可能会覆盖掉其他元素产生错误  
       {  
              if (a[begin1] < a[begin2])  
              {  
                     tmp[index++] = a[begin1++];  
              }  
              else  
              {  
                     tmp[index++] = a[begin2++];  
              }  
       }  
       while(begin1 <= end1)  
       {  
              tmp[index++] = a[begin1++];  
       }  
       while (begin2 <= end2)  
       {  
              tmp[index++] = a[begin2++];  
       }  
       while (begin <= end)                                     //将辅助数组中的元素再拷贝到原数组中  
       {  
              a[begin] = tmp[begin++];  
       }  
}  
void MergeSort(int *a,int begin,int end)  
{  
       assert(a);  
       int *tmp = new int[end-begin+1];  
       _MergeSort(a,begin,end,tmp);  
       delete[] tmp;  
}  

计数排序主要思想:
给定一组要排序的序列,找出这组序列中的最大值,然后开辟一个最大值加1大小的数组,将这个数组里面的元素全部置零,然后用这个数组统计出要排序的序列中各个元素出现的次数。等到统计完成的时候,排序就已经完成了。

基数排序的主要思想:
基数排序又称”桶子法”,他从低位开始将待排序的数按照这一位的值放到相应的编号为0到9的桶中。等到低位排完之后得到一个序列,再将这个序列按照次低位的大小进入相应的桶中。以此类推,直到将所有的位都排完之后,这组数就已经有序了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值