c++排序问题

1、直接排序法--稳定排序

  1. 对于第K个元素,将该元素的值存储在零时变量中,比较第前一个元素与该元素的大小,如果大于该元素就将前一个元素往后移动一步;
  2. 比较前面第二个元素与该元素的大小,如果大于该元素就将前第二个元素往后移动一步;
  3. 重复上述过程直到找到小于等于原来第K个元素(保存在零时变量中)的位置,并将第K个元素插入到这个元素的后面。或者找不到小于等于第K个元素的位置,就将原来第K个元素插入到数组的首地址。

代码如下:

//直接排序法-从小到大
void InsertSort(int arr[],int n)
{
    for (int i =0;i <n;++i)
    {
        for(int j = i;j > 0;--j)
        {
            if(arr[j] < arr[j -1])
            {
                int temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
            }
        }
    }
}
void InsertSort2(vector<int> &num)
{
    for(int i = 0;i < num.size();++i)
    {
        for(int j = i;j > 0;--j)
        {
            if(num[j] < num[j - 1])
            {
                int temp = num[j];
                num[j] = num[j-1];
                num[j-1] = temp;
            }
        }
    }
}

2、冒泡排序法 --稳定排序

  1. 将第一个元素与第二个元素比较大小,如果第一个元素大于第二个元素则调换他们两的位置;
  2. 比较第二个元素和第三个元素的大小,如果第二个元素大于第三个元素则调换他们两的位置;
  3. 依次类推,进行两两元素的比较和交换,最终最大的元素排在了最后面;
  4. 重复1到3过程,直到所有元素都排序。

代码如下:

//冒泡排序法
void BubbleSort(int arr[], int n)
{
    for (int i = 0; i < n - 1; i++) 
    {
        for (int j = 0; j < n - i - 1; j++) 
        {
            if (arr[j] > arr[j + 1]) 
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}
void BubbleSort2(int arr[], int len)
{
    int i,temp;
    //记录位置,当前所在位置和最后发生交换的地方
    int current,last = len - 1;
    while(last > 0) 
    {
        for(i = current = 0;i < last;++i)
        {
            if(arr[i] > arr[i+1])
            {
                temp = arr[i];
                arr[i] = arr[i+1];
                arr[i+1] = temp;
                //记录当前的位置,如果没有发生交换current值即for循环初始化的0
                current = i;
            }
        }
        //若current = 0即已经没有可以交换的元素了,即已经有序了
        last = current;
    }
}

3、快速排序法--不稳定排序

//快速排序法
//平均时间复杂度:O(NlogN)
//最坏情况复杂度:O(N^2)
//不稳定排序--1
void quicksortHelper(vector<int>& a, int start, int end)
{
    if (start >= end) return;
    int l = start, r = end;
    int pivot = a[(end - start) / 2 + start];
    while (l <= r)
    {
        while (l <= r && a[r] > pivot)  r--;
        while (l <= r && a[l] < pivot)  l++;
        if (l <= r) swap(a[l++], a[r--]);
    }
    quicksortHelper(a, start, r);
    quicksortHelper(a, l, end);
}
void quicksort(vector<int>& a)
{
    quicksortHelper(a, 0, a.size() - 1);
}
//指针的形式--2
void QuickSort(int *p, int l, int r)
{
    if (l< r)
    {
        int i = l, j = r, x = p[l];
        while (i < j)
        {
            while (i < j && p[j] >= x) // 从右向左找第一个小于x的数 
                j--;
            if (i < j)
                p[i++] = p[j];
            while (i < j && p[i]< x) // 从左向右找第一个大于等于x的数 
                i++;
            if (i < j)
                p[j--] = p[i];
        }
        p[i] = x;
        QuickSort(p, l, i - 1); // 递归调用 
        QuickSort(p, i + 1, r);  
    }
}

4、希尔排序--不稳定排序

     希尔排序算法是先将要排序的一组数按照某个增量d分成若干组,对每组中的元素进行排序,然后在用更小的增量来进行再次分组,并给每个分组重新排序,直到增量为1时,整个要排序的数被分成一组,排序结束。

      形象点说,例如[R1 ,R2 , R3, R4,R5,R6,R7,R8],先增量d =len/2 =4 ,则先分成[R1 R5] ,[R2 R6] ,[R3 R7] ,[R4 R8]四组,进行组内排序;再d=d/2 =2,分成[R1 R3 R5R7] 和 [R2 R4 R6 R8]两组,组内排序;再d=d/2=1,整个数组只剩一个大的分组[R1 , R2 , R3, R4,R5,R6,R7,R8],组内排序。全部结束。

代码如下:

//希尔排序-不稳定排序-从小到大
void shell_sort(int a[],int len)
{
    int d,i,j,temp;
    for(d=len/2;d>0;d=d/2)
    {
        for(i=d;i<len;i++)
        {
            temp= a[i];
            for(j=i-d;j>=0&&temp<a[j];j-=d)
            {
                a[j+d]=a[j];
            }
            a[j+d]=temp;
        }
    }
}

5、堆排序--不稳定排序-原理不是很清晰

代码如下:

//堆排序
//建堆的平均时间是:O(N)
//建堆的最坏情况是:O(NlogN)
//删除元素的时间是:O(logN)
//整个排序平均时间复杂度:O(N+NlogN)=O(NlogN)
//最坏情况复杂度:O(NlogN)
//不稳定排序
//建立一个大顶堆O(n),要求就是 把最大的元素 移动到堆顶 也就是a[0]
void make_heap(vector<int>& a, int size) //size的当前堆的大小,也就是数组的前size个数
{
    for (int i = size - 1; i > 0; i--)
    {
        if (i % 2 && a[i] > a[(i - 1) / 2])//奇数
            swap(a[i], a[(i - 1) / 2]);
        else if (i % 2 == 0 && a[i] > a[(i - 2) / 2])//偶数
            swap(a[i], a[(i - 2) / 2]);
    }
}

void heapsort(vector<int>& a)
{
    int n = a.size();
    while (n)
    {
        make_heap(a, n); //每次把新的最大元素移到堆顶,也就是a[0]
        n--;
        swap(a[0], a[n]); //然后把当前最大移动到后面来作为排好序的元素
    }
}

6、归并排序--稳定排序

归并排序就是利用归并思想实现的排序方法。原理:假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列长度为1,然后再两两归并,得到[n/2]个长度为2或1的有序子序列;再两两归并….,如此重复,直到的一个长度为n的有序序列为止,称为2路归并排序。

代码如下:

//归并排序
//平均时间复杂度:O(NlogN)
//稳定排序
vector<int> mergeHelper(vector<int> &a, int left, int right)
{
    if (left == right) return vector<int> (1, a[left]);
    int mid = (right - left) / 2 + left;
    vector<int> l = mergeHelper(a, left, mid);
    vector<int> r = mergeHelper(a, mid + 1, right);
    //merge
    vector<int> ret;
    int ll = 0, rr = 0;
    while (ll < l.size() && rr < r.size())
    {
        if (l[ll] <= r[rr])     ret.push_back(l[ll++]);
        else                    ret.push_back(r[rr++]);
    }
    while (ll < l.size()) ret.push_back(l[ll++]);
    while (rr < r.size()) ret.push_back(r[rr++]);
    return ret;
}

void mergesort(vector<int>& a)
{
    a = mergeHelper(a, 0, a.size() - 1);
}

猜你喜欢

转载自blog.csdn.net/hi_baymax/article/details/82048210