【liuyubobobo-算法与数据结构】第二章 排序基础


持续学习&持续更新中…

守破离


说明

  • 默认从小到大进行升序排序。
  • 什么是小,什么是大,是可以自定义的。
  • 你认为什么是大,什么就是大;你认为什么是小,什么就是小。
  • 因此,升序排序就是降序排序;降序排序同样也是升序排序。

为什么要学习O(n ^ 2)的排序算法

在这里插入图片描述

准备工作

sort_helper.h
#pragma once
#ifndef LEARN_ALGO_AND_DS_WITH_LIUYUBO_SORT_HELPER
#define LEARN_ALGO_AND_DS_WITH_LIUYUBO_SORT_HELPER

#include <iostream>
#include <ctime>
#include <cassert>

namespace sort_helper {

	//[rangeL, rangeR]
	int* generateRandomArray(int count, int rangeL, int rangeR) {
		assert(count > 0);
		assert(rangeL <= rangeR);
		int* array = new int[count];
		int delta = rangeR - rangeL + 1;
		srand(time(NULL));
		for (int i = 0; i < count; i++) {
			array[i] = rand() % delta + rangeL;
		}
		return array;
	}

	int* generateNearlyOrderedArray(int count, int swapTimes) {
		assert(count > 0);
		assert(swapTimes > 0);
		int* array = new int[count];
		for (int i = 0; i < count; i++) {
			array[i] = i;
		}
		srand(time(NULL));
		for (int i = 0; i < swapTimes; i++) {
			int randomA = rand() % count;
			int randomB = rand() % count;
			std::swap(array[randomA], array[randomB]);
		}
		return array;
	}

	int* copyArray(int* arr, int length) {
		int* array = new int[length];
		for (int i = 0; i < length; i++) {
			array[i] = arr[i];
		}
		return array;
	}

	void printlnArray(int array[], int length) {
		if (1) return;
		for (int i = 0; i < length; i++) {
			std::cout << array[i] << ' ';
		}
		std::cout << std::endl;
	}

	void printlnArrayWithInfo(const char* info, int array[], int length) {
		if (1) return;
		std::cout << info;
		printlnArray(array, length);
	}

	bool isArcOrderArray(int array[], int length) {
		assert(array != NULL);
		assert(length > 0);
		for (int i = 1; i < length; i++) {
			if (array[i - 1] > array[i]) return false;
		}
		return true;
	}

	void assertIsArcOrderArray(int array[], int length) {
		//bool flag = isArcOrderArray(array, length);
		//if (!flag) {
		//	cout << "测试未通过!" << endl;
		//}
		assert(isArcOrderArray(array, length));
	}

	void testSortArray(const char* info, void(*fun)(int[], int), int* arr, int length) {
		int* array = sort_helper::copyArray(arr, length);
		clock_t startTime = clock();
		fun(array, length);
		clock_t endTime = clock();
		std::cout << info << " 耗时:" << ((double)(endTime - startTime)) / CLOCKS_PER_SEC << "s -> ";
		printlnArray(array, length);
		assertIsArcOrderArray(array, length);
		delete[] array;
	}

}

#endif // !LEARN_ALGO_AND_DS_WITH_LIUYUBO_SORT_HELPER

main函数
#include <iostream>
#include "sort_helper.h"
int main() {
	int count = 10000;
	//int rangeL = 1;
	//int rangeR = 10000;
	//int* array = sort_helper::generateRandomArray(count, rangeL, rangeR);
	int* array = sort_helper::generateNearlyOrderedArray(count, 100);
	sort_helper::printlnArrayWithInfo("original : ", array, count);

	sort_helper::testSortArray("selectionSort", selectionSort, array, count);
	sort_helper::testSortArray("insertionSort1", insertionSort1, array, count);
	sort_helper::testSortArray("insertionSort2", insertionSort2, array, count);

	sort_helper::printlnArrayWithInfo("original : ", array, count);
	delete[] array;
	return 0;
}

选择排序 O(n ^ 2)

  • 排序前:

在这里插入图片描述

  • 排序后:

在这里插入图片描述

排序过程—动画演示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

实现
void selectionSort(int array[], int length) {
	for (int i = 0; i < length; i++) {
		int minIndex = i;
		for (int j = i + 1; j < length; j++) {
			if (array[j] < array[minIndex]) {
				minIndex = j;
			}
		}
		std::swap(array[minIndex], array[i]);
	}
}

插入排序 O(n ^ 2)

  • 对于一个近乎有序的数组来说,插入排序的性能很好,甚至会好于O(logn)级别的排序算法。
  • 因此插入排序有很重要的实际意义
  • 因为很多时候我们处理的真实的数据就是近乎有序的。
  • 插入排序还可以使用二分搜索进行优化。
  • 插入排序还是希尔排序的底层排序。
  • 插入排序在最优的情况下,也就是说我们要排序的内容是一个完全有序的数组时,插入排序就会变为**O(n)**级别的算法。

在这里插入图片描述

排序过程—动画演示

在这里插入图片描述

实现
void insertionSort1(int array[], int length) {
	for (int i = 1; i < length; i++) {
		int currentIndex = i;
		while (currentIndex > 0 && array[currentIndex] < array[currentIndex - 1]) {
			std::swap(array[currentIndex], array[currentIndex - 1]);
			currentIndex--;
		}
	}
}
排序过程—改进—动画演示

在这里插入图片描述

改进—实现
void insertionSort2(int array[], int length) {
	for (int i = 1; i < length; i++) {
		int currentIndex = i;
		int currentElement = array[currentIndex];
		while (currentIndex > 0 && currentElement < array[currentIndex - 1]) {
			array[currentIndex] = array[currentIndex - 1];
			currentIndex--;
		}
		array[currentIndex] = currentElement;
	}
}

参考

liuyubobobo: 算法与数据结构-综合提升 C++版.

课程代码仓库: 算法与数据结构-综合提升 C++版.


本文完,感谢您的关注支持!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值