您的位置:首页 > 其它

排序算法--冒泡排序,归并排序,快速排序

2016-08-29 18:01 405 查看
冒泡排序:

属于交换排序的一种。

很好理解的交换排序是这样的:

for (int i = 0; i < n; ++i)
for (int j = i+1; j < n; ++j)
{
if (nums[i] > nums[j])
swap(nums[i], nums[j])
}


这个算法的逻辑是从头到尾扫描元素,将这个元素和它后面的所有元素进行比较,如果有比它更小的,那就交换,最后交换的一定是最小的,然后元素指针i后移,再比较它后边的所有元素。

冒泡算法和这个算法类似,不同之处就在于两个for循环,它是交换相邻两个元素,完成一次内循环,最大的元素就跑到了最后一个位置。代码为:

for (int i = 0; i < n - 1; ++i)
for (int j = 0; j < n - i -1; ++j)
{
if (nums[j] > nums[j + 1])
swap(nums[j], nums[j + 1])
}


第一层for循环用来控制已经排好序的元素,第二层for循环,用来将未排好序的元素相邻元素比较。循环次数中,为什么要减一呢,那是因为元素要和它下一个元素比较,如果不减一,数组下标就会越界。

归并排序:

这个排序是用递归来做的。需要定义一个merge()函数(归并函数),这个函数的目的是将两个数组归一为一个有序数组。这个merge()函数的参数有待排序数组nums, 第一个元素下标,中间元素下标,最后一个元素下标。merge函数定义如下:

void merge(int nums[], int first, int mid, int last)
{
int * temp = new int[last - mid + 1];
int i = first;
int j = mid + 1;
int k = 0;
// 这里是核心,也就是归并
while (i <= mid && j <=last)
{
if (nums[i] < nums[j])
temp[k++] = nums[i++];
else
temp[k++] = nums[j++];
}
// 归并完了之后,要判断谁还有剩下的,将剩下的放到数组temp中
while (i <= mid)
temp[k++] = nums[i++];
while (j <= last)
temp[k++] = nums[j++];
// 然后将temp中的值拷贝到原数组中
i = first;
k = 0;
while (i <= last)
nums[i++] = temp[k++];
}


上边是归并排序的归并部分。还需要定义一个归并排序函数,用来做递归用。

void mergeSort(int nums[], int first, int last)
{
// 递归函数返回
if (first >= last)
return;
// 否则,继续细分数组,前一半,后一半
int mid = (first + last) / 2;
mergeSort(nums, first, mid);
mergeSort(nums, mid + 1, last);
// 一前一后都归并排序好了,调用归并函数开始归并
merge(nums, first, mid, last);
}


这里需要注意的是,last指针指的是最后一个元素。

快速排序:

快速排序的核心就是有一个pivot,我们叫它“基准”。快速排序和归并排序一样,也是用递归来实现的。

做法是: 先定义两个指针i,j。i指向第一个元素,j指向最后一个元素。先将pivot于j所指向的元素比较,若比它大,j--,若比它小,把j所指向的元素给i,i++;再开始pivot和i所指向的元素比较,若i所指向的元素比pivot大,则将i所指向的元素赋给j,j--。

也就是说先从后向前扫描,找到比它小的,再掉转方向,从前往后扫描,找打比它大的,再掉转方向,直到i和j相遇,算法结束。

void quickSort(int nums[], int first, int last)
{
if (first >= last)
return;
// 已数组的第一个元素为基准
int pivot = nums[first];
int i = first;
int j = last;
// 首先要有大循环的结束条件,那就是 i < j
while ( i < j)
{
while ( i < j && nums[j] >= pivot)
j--;
nums[i] = nums[j];
while (i < j && nums[i] <= pivot)
i++;
nums[j] = nums[i];
}
nums[i] = pivot;
quickSort(nums, first, i - 1);
quickSort(nums, i + 1, last);
}


这里需要注意的是:

1. 必需有递归结束函数

2. 每扫描一次,也要判断一次i是否小于j

3. 如果元素等于基准,就不移动。

打拳时间到了,先记录这三个算法吧。

若有不对之处,敬请指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐