首页 > 编程语言 > 详细

排序整理(c++实现),搭配图解

时间:2021-03-29 09:04:41      阅读:37      评论:0      收藏:0      [点我收藏+]

十大排序算法

技术分享图片
技术分享图片
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。

不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。

时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。

空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

元素的移动次数与关键字的初始排列次序无关的是:基数排序

元素的比较次数与初始序列无关是:选择排序

算法的时间复杂度与初始序列无关的是:选择排序

1.快速排序

方法

假如我们要排序这几个数 6 1 2 7 9 3 4 5 10 8

我们都是先找左边第一个数用作一开始作比较的基数就是6,然后右边开始比较,假设左边的哨兵是i,右边的是j。

从j开始找到比6小的第一个数,停下来。在从左边的i开始找,找到第一个比6大的书停下来。最后是i停到了7,停在了5上面。

然后对两个哨兵进行交换
技术分享图片
技术分享图片
第一次交换结束

然后在按照刚刚的顺序,j在向左寻找,找到4比6小,i向右寻找,找到9比6大,之后交换
技术分享图片
第二次结束

j在向左,找到3比6小,但是当i移动的时候两个哨兵相遇了,所以本次循环停止。停在3上面。最后在把3和基准数6交换之后完成。
技术分享图片
以6为分界线,对左右边再次调用快速排序进行递归,算法完成
技术分享图片

代码:

从小到大
//快速排序(从小到大)
void quickSort(int left, int right, vector<int>& arr)
{
	if(left >= right)
		return;
	int i, j, base, temp;
	i = left, j = right;
	base = arr[left];  //取最左边的数为基准数
	while (i < j)
	{
		while (arr[j] >= base && i < j)
			j--;
		while (arr[i] <= base && i < j)
			i++;
		if(i < j)
		{
			temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;
		}
	}
	//基准数归位
	arr[left] = arr[i];
	arr[i] = base;
	quickSort(left, i - 1, arr);//递归左边
	quickSort(i + 1, right, arr);//递归右边
}
从大到小
//快速排序(从大到小)
void quickSort(int left, int right, vector<int>& arr)
{
	if(left >= right) //递归边界条件
		return;
	if(left < 0 || right >= arr.size())
	{
		cout << "error args! array bound." << endl;
		return;
	}//非法输入判断,防止数组越界
	int i, j, base, temp;
	i = left, j = right;
	base = arr[left];  //取最左边的数为基准数
	while (i < j)
	{
		while (arr[j] <= base && i < j)
			j--;
			while (arr[i] >= base && i < j)
			i++;
		if(i < j)
		{
			temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;
		}
	}
	//基准数归位
	arr[left] = arr[i];
	arr[i] = base;
	quickSort(left, i - 1, arr);//递归左边
	quickSort(i + 1, right, arr);//递归右边
}

2.冒泡排序

技术分享图片

方法

冒泡其实很好理解

冒泡就是把最大的东西放在后面(小到大)或把最小的放在后面(大到小)

方法就是在一次循环中遍历找到最大的数放到后面,找到一个比前面大的数就进行交换,

在从剩下的数中在重发刚刚的循环。完成

代码:

//冒泡排序
void BubbleSort(int* h, size_t len)
{
    if(h==NULL) return;
    if(len<=1) return;
    int temp;
    //i是次数,j是具体下标
    for(int i=0;i<len-1;++i)
    {
        for(int j=0;j<len-1-i;++j)
        {
            if(h[j]>h[j+1])
            {
                temp = h[j];
    		h[j+1] = h[j];
    		h[j] = temp;
            }   
        }
    }           
}

3.选择排序

技术分享图片

方法:

选择排序和冒泡的区别就是,他是最后交换,所以比冒泡做了优化,减少了交换次数。

方法就是用一个数做基准数,在一次循环中找到一个最大或最小的数,然后与最左或最右的数进行交换。

每次循环用相同方法。完成

代码

//选择排序
void SelectionSort(int* h, size_t len)
{
    if(h==NULL) return;
    if(len<=1) return;

    int minindex,i,j,temp;
    //i是次数,也即排好的个数;j是继续排
    for(i=0;i<len-1;++i)
    {
        minindex=i;
        for(j=i+1;j<len;++j)
        {
            if(h[j]<h[minindex]) minindex=j;
        }
        temp = h[j];//最后进行交换
    	h[j+1] = h[j];
    	h[j] = temp;
    }
}

4.插入排序

技术分享图片

方法

我的方法就是把要排列的数组看成两个数组

排序好的,和没有加入排序的。

每次从没有排序好的那一部分中取出一个数,和排序好的做比较,不符合要求就把数字向后移动一位留出空间,符合要求就进行插入操作。

void InsertSort(int a[], int len)
{
	int i, j, k; 
	int tmp;
	for (i = 1; i < len; i++)	{ 
		k = i;			//待插入元素位置
		tmp = a[k];	    //先拿出来
 
		for (j = i - 1; (j >= 0) && (a[j] > tmp); j--){
			a[j + 1] = a[j];			//只要大,则元素后移
			k = j;						//记录移动的位置
		} 
		a[k] = tmp;		//元素插入 
	} 
}

5.归并排序

方法

先把一个数组的所有的数字分成一半,一半,再一半,最后临时开辟的空间中排序合并。

技术分享图片
技术分享图片

void  MergeArray(int* arr, size_t left, size_t mid, size_t right, int* temp)
{
    if(arr==NULL) return;

    size_t i=left,j=mid+1,k=0;
    while(i<=mid && j<=right)
    {
        if(arr[i]<=arr[j])
        {
            temp[k++]=arr[i++];
            continue;
        }

        temp[k++]=arr[j++];
    }

    //将左边剩余元素填充进temp中
    while(i<=mid)
        temp[k++]=arr[i++];
	//将右边子数组剩余部分填充到temp中
    while(j<=right)
        temp[k++]=arr[j++];
	//将融合后的数据拷贝到原来的数据对应的子空间中
    memcpy(&arr[left],temp,k*sizeof(int));
}
//归并排序
void MMergeSort(int* arr, size_t left, size_t right, int* temp)
{
    if(left<right)
    {
        //分治
        size_t mid=(left+right)/2;
        MMergeSort(arr, left, mid, temp);
        MMergeSort(arr, mid+1,right, temp);
        MergeArray(arr,left, mid, right, temp);
    }
}

//void MergeSort(int* h, size_t len)
//{
    //if(h==NULL) return;
    //if(len<=1) return;
    //int* temp=(int*)malloc(len,sizeof(int));
    //MMergeSort(h, 0, len-1, temp);
    //memcpy(h,temp,sizeof(int)*len);
    //free(temp);
//}

6.希尔排序(就是分组的插入排序)

就是通过分组,再把分组里的书进行插入算法,这样比较的次数可能会减少。

分组一般是总数除2

void ShellSort(int a[], int len)
{
	int i, j, k, tmp;
	int gap = len;
 
	do{	
		//gap的选择可以有多中方案,如gap = gap/2,这里使用的是业界统一实验平均情况最好的,收敛为1
		gap = gap / 2;
		for (i = gap; i < len; i += gap)  //分成len/gap组
		{
			//每组使用插入排序
			k = i;
			tmp = a[k];
			for (j = i - gap; (j >= 0) && (a[j] > tmp); j -= gap){
				a[j + gap] = a[j];
				k = j;
			}
			a[k] = tmp; 
		}
	} while (gap > 1);
}

7.堆排序(用到完全二叉树)

堆分为两类:
1、最大堆(大顶堆):堆的每个父节点都大于其孩子节点;
2、最小堆(小顶堆):堆的每个父节点都小于其孩子节点;
技术分享图片
堆的存储:
一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如下图所示:
技术分享图片

实现图解

技术分享图片

// 从小到大排序
void Down(int array[], int i, int n) { // 最后结果就是大顶堆
    int temp;
    int parent = i;                    // 父节点下标
    int child  = 2 * i + 1;            // 子节点下标
    while (child < n) {
        if (child + 1 < n && array[child] < array[child + 1]) { // 判断子节点那个大,大的与父节点比较
            child++;
        }
        if (array[parent] < array[child]) { // 判断父节点是否小于子节点
            temp = array[parent];
            array[parent] = array[child];
            array[child] = temp;     // 交换父节点和子节点
            parent = child;                 // 子节点下标 赋给 父节点下标
        }
        child = child * 2 + 1; // 换行,比较下面的父节点和子节点
    }
}

void BuildHeap(int array[], int size) {
    for (int i = size / 2 - 1; i >= 0; i--) { // 倒数第二排开始, 创建大顶堆,必须从下往上比较
        Down(array, i, size);                 // 否则有的不符合大顶堆定义
    }
}

void HeapSort(int array[], int size) {
    BuildHeap(array, size); // 初始化堆
    for (int i = size - 1; i > 0; i--) {
        temp = array[0];
        array[0] = array[i];
        array[i] = temp; // 交换顶点和第 i 个数据
                           // 因为只有array[0]改变,其它都符合大顶堆的定义,所以可以从上往下重新建立
        Down(array, 0, i); // 重新建立大顶堆

    }
}

参考文章

https://www.cnblogs.com/chengxiao/p/6129630.html
https://blog.csdn.net/weixin_42109012/article/details/91668543
https://blog.csdn.net/qq_28584889/article/details/88136498

排序整理(c++实现),搭配图解

原文:https://www.cnblogs.com/sunnylinry/p/14590393.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!