常见的比较排序算法

比较排序是比较常见的排序算法,它分为以下几个类:

  • 交换排序:冒泡排序(BubbleSort)和快速排序(QuickSort)。
  • 插入排序:直接插入排序和希尔排序(ShellSort)。
  • 选择排序:选择排序(SelectSort)和堆排序(HeapSort)。

(一)交换排序:

void BubbleSort(int* arry, int size)
{
	for (int i = 0; i < size - 1; i++)
	{
		for (int j = 0; j < size - i - 1; j++)
		{
			if (arry[j] > arry[j + 1])
			{
				swap(arry[j], arry[j + 1]);
			}
		}
	}
}
//冒泡排序第一次优化(设置一个标志)
void BubbleSort(int* arry, int size)
{
	bool swaped = false;
	for (int i = 0; i < size; i++)
	{
		swaped = false;
		for (int j = 0; j < size - i - 1; j++)
		{
			if (arry[j] > arry[j + 1])
			{
				swap(arry[j], arry[j + 1]);
				swaped = true;
			}
		}
		if (!swaped)
		{
			break;
		}
	}
}
//冒泡排序第二次优化(去除已经有序的区间)
void BubbleSort(int* arry, int size)
{
	int lastswappos = size-1;
	int lastswappos_temp = size-1;
	for (int i = 0; i < size; i++)
	{
		lastswappos = lastswappos_temp;
		for (int j = 0; j < lastswappos; j++)//每次冒泡到最后一次交换的位置
		{
			if (arry[j] > arry[j + 1])
			{
				swap(arry[j], arry[j + 1]);
				lastswappos_temp = j;
			}
		}
		if (lastswappos==lastswappos_temp)
		{
			break;
		}
	}
}

冒泡排序是最简单的交换排序,在这里我们给出了2种优化方式。第一种是设置一个标志位标志在一趟排序中是否有过排序,如果没有则就排序完成,这种优化方式对于在一个数组的后半部分是有序的情况下提高了效率。第二种方式也相当于设置一个标志位,只是这个标志位是标志最后一次交换的数的下标。这种方法是有效的去除了已经有序的区间。

不管怎么优化,对于一般的数组冒泡排序的时间复杂度为O(N^2)。

快速排序:

//快速排序
void QuickSort(vector<int> &arry, int left, int right)
{
	if (left >= right)
		return;
	int lflag = left;
	int rflag = right - 1;
	int tmp = arry[left];
	while (lflag < rflag)
	{
		while ((lflag < rflag) && arry[rflag] >= tmp)
		{
			rflag--;
		}
		arry[lflag] = arry[rflag];
		while ((lflag < rflag) && arry[lflag] <= tmp)
		{
			lflag++;
		}
		arry[rflag] = arry[lflag];
	}
	swap(arry[lflag], tmp);
	QuickSort(arry, left, rflag - 1);//左子区间
	QuickSort(arry, rflag + 1, right);//右子区间
}

快速排序是利用了划分子问题的思想。每次选取区间的第一个数据作为中间值,将大于中间值的数据放在右边,否则放在左边。再将中间值的左右边看成一个子区间,递归的划分子区间,直到区间的左边下标大于或者等于右边下标结束。

快速排序是效率比大部分排序算法的速度要快。但是快速排序是一个递归思想,显然,对于内存有限的机器来说它不是一个好的选择。对于很长很长的数组来说也不是一个好的选择,递归的额层数越多,效率越低。

(二)选择排序:

一般的选择排序

void SelectSort(int* arry, int len)
{
	assert(arry);
	int flag = 0;
	while (flag != len - 1)
	{
		int tmp = arry[flag];
		for (int i = flag + 1; i < len - 1; i++)
		{
			if (arry[i] < tmp)
			{
				swap(arry[i], tmp);
			}
		}
		arry[flag] = tmp;
		flag++;
	}
}

一般的选择排序算法的时间复杂度为O(N^2)。

堆排序

void AdjustDown(int* a, size_t size, size_t parent)//下调函数
{
	size_t child = parent * 2 + 1;
	while (child < size)
	{
		if (child + 1 < size&&a[child] < a[child + 1])
			++child;
		if (a[parent] < a[child])
		{
			swap(a[parent], a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}
void HeapSort(int* a, size_t size)
{
	//建堆
	for (int i = (size - 2) / 2; i >= 0; --i)
		//i不能定义为size_t除法会溢出,翻转成一个很大的数
	{
		AdjustDown(a, size, i);
	}
	for (size_t i = 0; i < size; ++i)
	{
		swap(a[0], a[size - 1 - i]);
		AdjustDown(a, size - i - 1, 0);
	}
}

堆排序是利用大顶堆的性质,可以快速的找出最大值。依次找出最大值,排序完成。时间复杂度为

O(N*lgN)。

(三)插入排序

直接插入排序:

void InsertSort(int *a, size_t size)
{
	assert(a);
	for (size_t i = 1; i < size; ++i)
	{
		int tmp = a[i];
		size_t j = i;
		while (j > 0 && tmp < a[j - 1])
		{
			a[j] = a[j - 1];
			j--;
		}
		a[j] = tmp;
	}
}

在数组前面的有序序列里找到合适的位置将待插入数据插入,时间复杂度为O(N^2)。

希尔排序:

void ShellSort(int *a,int size)
{
        int gap = size / 2;
	while (1 <= gap) 
	{
		// 把距离为 gap 的元素编为一个组,扫描所有组
		for (int i = gap; i < size; i++)
		{
			int j = 0;
			int temp = a[i];
			// 对距离为 gap 的元素组进行排序
			for (j = i - gap; j >= 0 && temp < a[j]; j = j - gap)
			{
				a[j + gap] = a[j];
			}
			a[j + gap] = temp;
		}
		gap = gap / 2; // 减小增量
	}
}

gap是间隔增量。它控制序列向有序发展。

我们分割待排序记录的目的是减少待排序记录的个数,并使整个序列向基本有序发展。因此,我们需要采取跳跃分割的策略:将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序

希尔排序的时间复杂度是在O(N^1.25)~O(N^1.66)之间。希尔排序在逆序时效果最好,有序时效果最差,还不如直接排序。

时间: 2024-10-09 08:53:38

常见的比较排序算法的相关文章

数据结构常见的八大排序算法(详细整理)

https://www.jianshu.com/p/7d037c332a9d?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=weixin-friends 八大排序,三大查找是<数据结构>当中非常基础的知识点,在这里为了复习顺带总结了一下常见的八种排序算法.常见的八大排序算法,他们之间关系如下: 排序算法.png 他们的性能比较: 性能比较.png 下面,利用Python分别将他

数据结构——常见的十种排序算法

一.常见的十种排序算法: 冒泡排序.选择排序.插入排序.归并排序.快速排序.希尔排序.堆排序.计数排序.桶排序.基数排序 1.[知识框架] 补充:内部排序:整个排序过程完全在内存中进行. 外部排序:由于待排序记录数据量太大,内存无法容纳全部数据,需要借助外部存储. 二.排序方法 ?插入排序 1.算法思想 从待排序的第二个元素开始,向下扫描列表,比较这个目标值target与arr[i-1].arr[i-2]的大小,依次类推.如果target的值小于或等于每一个元素值,那么每个元素都会向右滑动一个位

常见的七大排序算法Java实现

/** * @author Javen * @Email [email protected] * 2015年12月9日 */ public class Sorting { static int[] array = new int[]{11, 31, 12, 5, 34, 30, 26, 38, 36, 18}; public static void main(String[] args) { //插入排序 System.out.println(array2String(sortInsert(ar

用JS实现的常见几种排序算法

1.快速排序法 /*快速排序法*/ function quickSort(a) { if (a.length <= 1) { return a; } var midLength = Math.floor(a.length / 2); var midValue = a.splice(midLength,1); var left = []; var right = []; for (var i = 0; i < a.length; i++) { if (a[i] < midValue) {

数据结构之常见的排序算法c语言实现

常见的简单排序算法有冒泡排序.选择排序.插入排序.快排.堆排序.归并排序.希尔排序等,这些排序的理论在网上有很多,这就只给出常见的排序算法源码,上学时候写的,不足之处欢迎大家指正. 下面几种排序的主函数入口为:     int main(int argc, char* argv[])         {      int i, len;      int a[] = {8,5,6,4,9,10,3,15,2,17};           len = (sizeof(a) / sizeof(a[0

用Java来写常见的排序算法

随着校招的临近 算法是校招中很重要的一个部分 总结了常见几种排序算法,各种算法的时间复杂度和空间复杂度大家也需要多了解下 package com.huwei.sort; /** * 各种排序算法 * * @author huwei * */ public class Sort { public static void main(String[] args) { int[] a = { 60, 57, 89, 47, 57, 98, 45, 35, 73 }; Sort sort = new So

8大排序算法图文讲解

排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 常见的内部排序算法有:插入排序.希尔排序.选择排序.冒泡排序.归并排序.快速排序.堆排序.基数排序等. 本文将依次介绍上述八大排序算法. 算法一:插入排序 插入排序示意图 插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入. 算法步骤: 1)将第一待排序序列第一

面试——8大排序算法图文讲解

排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 常见的内部排序算法有:插入排序.希尔排序.选择排序.冒泡排序.归并排序.快速排序.堆排序.基数排序等. 本文将依次介绍上述八大排序算法. 算法一:插入排序 插入排序示意图 插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入. 算法步骤: 1)将第一待排序序列第一

Java实现各种内部排序算法

数据结构中常见的内部排序算法: 插入排序:直接插入排序.折半插入排序.希尔排序 交换排序:冒泡排序.快速排序 选择排序:简单选择排序.堆排序 归并排序.基数排序.计数排序 直接插入排序: 思想:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中,直到全部记录插入完成. 性能:时间复杂度:最好o(n):有序,最坏o(n^2):逆序,平均o(n^2):空间复杂度o(1):稳定 1 public int[] straightInsertSort(int array[]){ 2 int