今天心血来潮复习了一下基本的排序算法,实现了一下,就顺便发上来咯。。
在代码里做了注释了-。-
也就不多说了,直接上代码吧。。
// order_algorithm.cpp: 定义控制台应用程序的入口点。
//author: netbin
#include "stdafx.h"
#include "iostream"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <vector>
//指定数组的大小
const int max_size = 50;
using namespace::std;
//插入排序
//时间复杂度O(n^2),空间复杂度O(n),是一个稳定算法;
//假定该数组有有序区和无序区:则不断地将无序区的第一个元素取出放置于有序区的正确位置;
//从i的位置开始,从后往前依次比较,如果nums[j]小于nums[i],则交换二者的位置;
//优化:我们可以知道插入排序的前部是有序的,则如果nums[j]>=nums[i],则表明,i之前的所有元素
//都符合这个特性,那么也就不需要再继续比较了;
void insert_sort(vector<int> &nums)
{
for (int i = 0; i < nums.size(); i++) {
for (int j = i; j > 0; j--) {
if (nums[j] < nums[j-1]) {
int temp = nums[j];
nums[j] = nums[j-1];
nums[j-1] = temp;
}
else
break;
}
}
}
//希尔排序
//时间复杂度 O(n^1.3),准确地说希尔排序的时间复杂度与增量序列有关
//它是一个不稳定的算法:因为可能数处于不同的组别内
//希尔排序是对插入排序的优化
void shell_sort(vector<int> &nums)
{
//gap是步长,步长每次减半;
//这里最后的gap/=2要注意。。刚开始写成了gap/2,没有等号,所有gap没作用,会造成死循环
for (int gap = nums.size() / 2; gap > 0; gap /= 2) {
//从gap位置开始,相当于直接插入排序的第2个元素开始;
for (int i = gap; i < nums.size(); i++) {
int temp = nums[i];
//相当于插入排序的j = i;
//同组内的无序数组的第一个元素的前一个数组。。。好像挺绕的-。-
int j = i - gap;
//同组内元素的比较
for (; j >= 0 && nums[j] > temp; j -= gap) {
//这里需要注意的是j的值变化的情况;
//第一次的j+gap=i #-。-
//其实也就是把大于nums[i]的值都后移
nums[j + gap] = nums[j];
}
//这里需要注意的是在上面的for循环中,最后还会执行一次j-=gap;
//所以这里的j+gap会等于上面结束时j的值
nums[j + gap] = temp;
}
}
}
//冒泡排序
//时间复杂度: O(n^2),空间复杂度:O(n)
//稳定性:是一个稳定算法
void bubble_sort(vector<int> &nums)
{
for (int i = 0; i < nums.size()-1; i++) {
for (int j = 0; j < nums.size() - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
}
//选择排序:从无序数组中选出最小(最大)的数,放到乱序数组的头部
//优化:同时选出最大和最小
void select_sort(vector<int> &nums)
{
for (int i = 0; i < nums.size(); i++) {
int min = i;
for (int j = i+1; j < nums.size(); j++) {
if (nums[j] < nums[min]) {
min = j;
}
}
int temp = nums[i];
nums[i] = nums[min];
nums[min] = temp;
}
}
//快速排序
void quick_sort(vector<int> &nums, int b, int e, vector<int> &temp)
{
int m = (b + e) / 2;
//判断是否只有一个元素
if (m != b) {
int lb = b;
int rb = e - 1;
for (int i = b; i < e; i++) {
//如果当前位置等于选中元素的位置,则跳过此次循环,进入下一次循环;
if (i == m) {
continue;
}
//如果当前位置元素的值小于选中的元素,则添加到临时数组的左边
if (nums[i] < nums[m]) {
temp[lb++] = nums[i];
}else{
//如果当前位置元素的值大于选中的元素,则添加到临时数组的右边
temp[rb--] = nums[i];
}
}
//循环结束时,temp数组中lb指向的位置就是在nums数组中选中元素所在的位置
temp[lb] = nums[m];
//将temp数组复制到nums数组中
for (int i = b; i < e; i++) {
nums[i] = temp[i];
}
//递归调用
quick_sort(nums,b,lb,temp);
quick_sort(nums, lb + 1, e, temp);
}
}
//归并排序
//时间复杂度:O(nlogn)
//归并排序是将元素分割为一个一个的小组,然后对每个小组再进行排序,然后再合并数组,分而治之的思想
//这种排序的方式与希尔排序的基本思想类似
void merge_array(vector<int> &nums, int b, int m, int e, vector<int> &temp)
{
int lb = b;
int rb = m;
int tb = b;
//在合并两个数组时,如果左边数组和右边的数组都未空
while (lb != m && rb != e) {
if (nums[lb] < nums[rb]) {
temp[tb++] = nums[lb++];
}
else {
temp[tb++] = nums[rb++];
}
}
//如果右边的已经空了,而左边没空,就将左边数组的剩余所有元素全部入数组
while (lb < m)
temp[tb++] = nums[lb++];
//如果左边的已经空了,而右边没空,就将右边数组的剩余所有元素全部入数组
while (rb < m)
temp[tb++] = nums[rb++];
//将此次合并存入临时数组的元素全部复制到nums数组中
for (int i = b; i < e; i++) {
nums[i] = temp[i];
}
}
void merge_sort(vector<int> &nums, int b, int e, vector<int> &temp)
{
int m = (b + e) / 2;
if (m != b) {
//将元素分割成一个一个的
merge_sort(nums, b, m, temp);
merge_sort(nums, m, e, temp);
//然后对这些元素组成的小组进行递归合并;
merge_array(nums, b, m, e, temp);
}
}
//堆排序
//建堆以及调整堆
void max_heapofy(vector<int> &nums, int beg, int end)
{
int curr = beg;
int child = curr * 2 + 1;
//不是最后一个结点
while (child < end) {
//判断子结点中哪个更大,用最大子节点来和父节点比较就可以了
if (child + 1 < end && nums[child + 1] > nums[child])
child++;
//如果父节点小于最大子节点,就交换值
if (nums[curr] < nums[child]) {
int temp = nums[curr];
nums[curr] = nums[child];
nums[child] = temp;
//调整之后可能会导致下面的子树不是最大堆,故而要重新调整
curr = child;
child = curr * 2 + 1;
}
else
//如果不需要调整,则结束此次循环
break;
}
}
void heap_sort(vector<int> &nums)
{
int n = nums.size();
//建堆
for (int i = n / 2 - 1; i >= 0; i--) {
max_heapofy(nums,i,nums.size());
}
//将堆顶(最大元素)和数组的最后一个值交换,然后再调整堆
for (int i = n - 1; i > 0; i--) {
int temp = nums[i];
nums[i] = nums[0];
nums[0] = temp;
max_heapofy(nums,0,i);
}
}
//初始化vector数组函数
void init_vec(vector<int> &nums)
{
srand((unsigned)time(NULL));
for (int i = 0; i < max_size; i++) {
nums.push_back(rand());
}
}
//输出结果,并清空vector
void print_clear(vector<int> &nums)
{
for (int i = 0; i < max_size; i++) {
cout << nums[i] << " ";
}
cout << endl;
nums.clear();
}
int main()
{
vector<int> nums;
//插入排序:测试结果成功
init_vec(nums);
time_t start = clock();
insert_sort(nums);
time_t end = clock();
cout << "插入排序测试结果:" << endl;
print_clear(nums);
printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);
//希尔排序:测试结果成功
init_vec(nums);
start = clock();
shell_sort(nums);
end = clock();
cout << "希尔排序测试结果:" << endl;
print_clear(nums);
printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);
//冒泡排序:成功
init_vec(nums);
start = clock();
bubble_sort(nums);
end = clock();
cout << "冒泡排序测试结果:" << endl;
print_clear(nums);
printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);
//选择排序:成功
init_vec(nums);
start = clock();
select_sort(nums);
end = clock();
cout << "选择排序测试结果:" << endl;
print_clear(nums);
printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);
//快速排序:成功
vector<int> temp(max_size);
init_vec(nums);
start = clock();
quick_sort(nums,0,nums.size(),temp);
end = clock();
temp.clear();
cout << "快速排序测试结果:" << endl;
print_clear(nums);
printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);
//归并排序:失败-。- 数组下表越界 #因为在快速排序时清空了temp数组,所以导致了这次的数组越界
init_vec(temp);
init_vec(nums);
start = clock();
merge_sort(nums, 0, nums.size(), temp);
end = clock();
temp.clear();
cout << "归并排序测试结果:" << endl;
print_clear(nums);
printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);
//堆排序:失败-。-最后一个元素没有排好序
//修复了 #-。-
init_vec(nums);
start = clock();
heap_sort(nums);
end = clock();
temp.clear();
cout << "堆排序测试结果:" << endl;
print_clear(nums);
printf("运行时间 : %f\n", double(end - start) / CLOCKS_PER_SEC);
system("pause");
return 0;
}