排序算法总结

本文总结了内部排序算法,包括冒泡排序、插入排序、希尔排序、选择排序、堆排序、归并排序和快速排序。详细介绍了每种排序算法的思想、时间复杂度和稳定性,并给出了最佳和最坏情况的性能分析。

排序算法可以分为内部排序外部排序

内部排序是数据记录在内存中进行排序。

而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。

常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。

用一张图概括:

 

1.冒泡排序

思想:从后往前将数组中的元素两两比较,交换两者的位置取小的那一个元素,直到数组开头。重复这一过程,直到最后两个元素比较之后交换位置

(1)平均时间复杂度O(n2),是稳定排序

(2)最坏时间复杂度O(n2),逆序的时候

(3)最好时间复杂度O(n),顺序的时候

void bubble_sort(vector<int> &array)
    {
        int n = array.size();
        for(int i = 1; i <= n-1; i++)
        {
            bool flag = false;
            for(int j = 0; j < n - i; j++)
            {
                if(array[j] > array[j+1])
                {
                    flag = true;
                    swap(array[j], array[j+1]);
                }
            }
            if(!flag)
                break;
        }
    }


这里写图片描述
2.插入排序

从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置

(1)平均时间复杂度O(n2),稳定排序

(2)逆序情况每次循环都要比较n次,时间复杂度O(n)

(3)最好情况顺序,时间复杂度O(n)

    void insert_sort(vector<int> &array)
    {
        int n = array.size();
        for(int i = 1; i <= n-1; i++)
        {
            int temp = array[i];
            int j;
            for(j = i-1; j >= 0; j--)
            {
                if(temp < array[j])
                {
                    array[j+1] = array[j];
                }
                else
                {
                    array[j+1] = temp;
                    break;
                }
            }
        }
    }


这里写图片描述
3.希尔排序(改进简单插入排序,每次交换相隔一定距离的元素),希尔排序是不稳定排序

void shellsort(int A[],int N,int incre[],int M)
{
	int i,j,k,l,increment,temp;
	for(i=0;i<M;i++)
	{
		increment=incre[i];
		for(j=increment;j<N;j=j++)
		{
			temp=A[j];
			for(k=j;k-increment>=0;k=k-increment)
			{
				if(temp>=A[k-increment])
					break;
				else
					A[k]=A[k-increment];
			}
			A[k]=temp;
		}
		printf("第%d次排序:",i);
		for(l=0;l<N;l++)
			printf("%d ",A[l]);
		printf("\n");
	}
}

4.选择排序

从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾

(1)平均时间复杂度O(n2),不稳定排序

(2)最坏和最好情况都是O(n2),因为每个循环都要比较n次

void select_sort(vector<int> &array)
    {
        int n = array.size();
        for(int i = 0; i < n-1; i++)
        {
            int min = i;
            for(int j = i+1; j < n; j++)
            {
                if(array[j] < array[min])
                    min = j;
            }
            if(min != i)
                swap(array[min], array[i]);
        }
    }

5.堆排序

  • 创建一个堆 H[0……n-1];

  • 把堆首(最大值)和堆尾互换,调整剩余的堆,使堆首值最大。

  • 重复此步骤,直至堆的大小变为1

(1)堆排序是不稳定排序

(2)最好和最坏时间复杂度都是O(nlogn)

void adjust(vector<int> &num, int p, int N)
    {
        /* 将N个元素的数组中以num[p]为根的子堆调整为最大堆 */
        int temp = num[p];
        int parent, child;
        for(parent = p;(2*parent+1) < N; parent = child)
        {
            child = 2*parent +1;
            if( (child+1 < N ) && (num[child]<num[child+1]))
                child++;
            if(temp >= num[child])
                break;
            else
                num[parent] = num[child];
        }
        num[parent] = temp;
    }
    void heap_sort(vector<int> &array)
    {
        int n = array.size();
        for(int i = n/2-1; i >= 0; i--)//将数组调整为最大堆
            adjust(array, i, n);

        for(int i = n-1; i > 0; i--)
        {
            swap(array[i], array[0]);/* 删除最大堆顶 */
            adjust(array, 0, i);//调整堆
        }
    }

6.归并排序

(1)是稳定排序

(2)最坏和最好时候的时间复杂度都是O(nlogn)

#include<iostream>
#include<vector>

using namespace std;

void merge(vector<int> &array, int L, int R, int RightEnd)
{
    int num = RightEnd-L+1;
    int LeftEnd = R-1;
    vector<int> temp(num);

    int i = 0;
    while(L <= LeftEnd && R <= RightEnd)
    {
        if(array[L] < array[R])
            temp[i++] = array[L++];
        else
            temp[i++] = array[R++];
    }
    while(L <= LeftEnd)
        temp[i++] = array[L++];
    while(R <= RightEnd)
        temp[i++] = array[R++];

    for(int i = num-1; i >= 0; i--)
        array[RightEnd--] = temp[i];
}
void merge_sort(vector<int> &array, int start, int end)
{
    if(start < end)
    {
        int mid = (start + end)/2;
        merge_sort(array, start, mid);
        merge_sort(array, mid+1, end);
        merge(array, start, mid+1, end);
    }
}

int main()
{
    int n;
    cin>>n;
    vector<int> array(n);
    for(int i = 0; i < n; i++)
        cin>>array[i];
    merge_sort(array, 0, n-1);
    for(int i = 0; i < n; i++)
        cout<<array[i]<<endl;
    return 0;
}


这里写图片描述
这里写图片描述
这里写图片描述
7.快速排序

  • 从数列中挑出一个元素,称为 “基准”(pivot);

  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序

(1)不是稳定排序

(2)最好时间复杂度O(nlogn),最坏时间复杂度O(n2),最坏情况是每次基准都是最小或者最大的数,没有分成两个子序列

#include<iostream>
#include<vector>

using namespace std;

int partition(vector<int> &array, int low, int high)
{
    int pivot = array[low];
    while(low < high)
    {
        while(high > low && array[high] >= pivot)
            high--;
        array[low] = array[high];
        while(low < high && array[low] < pivot)
            low++;
        array[high] = array[low];
    }
    array[low] = pivot;
    return low;
}
void quick_sort(vector<int> &array, int start, int end)
{
    if(start < end)
    {
        int index = partition(array, start, end);
        quick_sort(array, start, index);
        quick_sort(array, index+1, end);
    }
}

int main()
{
    int n;
    cin>>n;
    vector<int> array(n);
    for(int i = 0; i < n; i++)
        cin>>array[i];
    quick_sort(array, 0, n-1);
    for(int i = 0; i < n; i++)
        cout<<array[i]<<endl;
    return 0;
}

 

 

 

 

 

 



 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值