几种常见的排序算法

冒泡排序

冒泡排序算法的运作如下:

1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。

2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

3、针对所有的元素重复以上的步骤,除了最后一个。

4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

void BubbleSort(int arr[], int n)
{
	int i = 0, j =0;    
	for(i = 0; i < n; i++)
		for(j = 0; j < n - 1 - i; j++)
		{
			if(arr[j] > arr[j + 1])
			{
				arr[j] = arr[j] ^ arr[j+1];
				arr[j+1] = arr[j] ^ arr[j+1];
				arr[j] = arr[j] ^ arr[j+1];
			}            
		}    
}

交换两个数据,可以用用临时变量,也可用以下的两个方法
a = a^b;
b = a^b;
a = a^b;
或者
a = a + b;
b = a - b;
a = a - b;

冒泡排序变异版-鸡尾酒排序法

/**
 * 鸡尾酒排序法
 * 
 *正常冒泡排序法,每次遍历都是向一个方向冒出最值,
 *而鸡尾酒排序法是变异的冒泡排序法,往返方向找出最值
 */
public void sort(int[] a) {
	//需要来回a,length/2趟
	for (int i = 0; i < a.length / 2; i++) {
		//类冒泡,交换最大值至右端
		for (int j = i; 1 + j < a.length - i; j++)
			if (a[j] > a[1 + j])
				Arr.swap(a, j, 1 + j);
		//类冒泡,交换最小值至左端
		for (int j = a.length - i - 1; j > i; j--)
			if (a[j - 1] > a[j])
				Arr.swap(a, j - 1, j);
	}
}

冒泡排序改进版

/**
 *改进的冒泡算法,在第i次遍历时,若没有交换数据,说明剩余的数据已经是有序的
 */
void BubbleSort(int arr[]) {
    boolean didSwap;
    for(int i = 0, len = arr.length; i < len - 1; i++) {
        didSwap = false;
        for(int j = 0; j < len - i - 1; j++) {
            if(arr[j + 1] < arr[j]) {
                swap(arr, j, j + 1);
                didSwap = true;
            }
        }
        if(didSwap == false)
            return;
    }    
}


选择排序

选择排序的工作原理:

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

/**
 * @brief 选择排序
 *
 * @param list[] 要排序的数组
 * @param n 数组中的元素数量
 */
void SelectSort(int *list, int list_size)
{
    int i, j; // 用于循环
    int min_index; // 当前最小值的 index
    int temp; // 用于交换
    // 最后一个元素不用排了, 所以可以 len - 1; 少一次循环
    for (i = 0; i < list_size - 1; ++i)
    {
        // 假定当前的元素就是最小的
        min_index = i;
        // 查找剩下的元素当中最小的
        for (j = i; j < list_size; ++j)
        {
            if (list[j] < list[min_index])
            {
                min_index = j;
            }
        }
        // 如果找到了比当前小的, 就把当前元素与之交换
        if (min_index != i)
        {
            temp = list[i];
            list[i] = list[min_index];
            list[min_index] = temp;
        }
    }
}

归并排序

归并操作的过程如下:
1、申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2、设定两个指针,最初位置分别为两个已经排序序列的起始位置
3、比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4、重复步骤3直到某一指针到达序列尾
5、将另一序列剩下的所有元素直接复制到合并序列尾

/**
 * @brief 归并排序
 *
 * @param *list 要排序的数组
 * @param n 数组中的元素数量
 */
void MergeSort(int *list, int list_size)
{
    if (list_size > 1)
    {
        // 把数组平均分成两个部分
        int *list1 = list;
        int list1_size = list_size / 2;
        int *list2 = list + list_size / 2;
        int list2_size = list_size - list1_size;
        // 分别归并排序
        merge_sort(list1, list1_size);
        merge_sort(list2, list2_size);
 
        // 归并
        merge_array(list1, list1_size, list2, list2_size);
    }
}
 
/**
 * @brief 归并两个有序数组
 *
 * @param list1
 * @param list1_size
 * @param list2
 * @param list2_size
 */
void merge_array(int *list1, int list1_size, int *list2, int list2_size)
{
    int i, j, k;
    i = j = k = 0;
 
    // 声明临时数组用于存储归并结果
    int *list = malloc((list1_size + list2_size)*sizeof(int));
 
    // note: 只要有一个数组到达了尾部就要跳出
    // 也就是说只有两个都没有到达尾部的时候才执行这个循环
    while (i < list1_size && j < list2_size)
    {
        // 把较小的那个数据放到结果数组里, 同时移动指针
        list[k++] = list1[i] < list2[j] ? list1[i++] : list2[j++];
    }
 
    // 如果 list1 还有元素,把剩下的数据直接放到结果数组
    while (i < list1_size)
    {
        list[k++] = list1[i++];
    }
 
    // 如果 list2 还有元素,把剩下的数据直接放到结果数组
    while (j < list2_size)
    {
        list[k++] = list2[j++];
    }
 
    // 把结果数组 copy 到 list1 里
    for (int ii = 0; ii < (list1_size + list2_size); ++ii)
    {
        list1[ii] = list[ii];
    }
    free(list); 
}

快速排序

快速排序的步骤
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。

/** 
 * @brief 快速排序
 * 
 * @param list  要排序的数组
 * @param lIndex 左下标
 * @param rIndex 右下标
 */  
void QuickSort(int list[], int lIndex, int rIndex)
{
    if (lIndex < rIndex)
    {
        int i = lIndex, j = rIndex, x = list[lIndex];//第一个元素作为基准数
        while (i < j)
        {
            while(i < j && list[j] >= x) // 从右向左找第一个小于x的数
                j--; 
            if(i < j)
                list[i++] = list[j];

            while(i < j && list[i] < x) // 从左向右找第一个大于等于x的数
                i++; 
            if(i < j)
                list[j--] = list[i];
        }
        list[i] = x;
        QuickSort(list, lIndex, i - 1); // 递归调用
        QuickSort(list, i + 1, rIndex);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

callinglove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值