冒泡排序
冒泡排序算法的运作如下:
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);
}
}