数据结构算法学习总结-慕课网(四)插入排序的优化(从小到大)

原创 2018年04月16日 10:23:28

数据结构算法学习总结-慕课网(四)插入排序的优化(从小到大)

1.回顾

插入排序

template<typename T>

void insertSort(T arr[],int n){
	for(int i = 1;i<n;i++){
		for(int j = i;j>0;j--){
			if(arr[j] < arr[j-1]){
				swap(arr[j],arr[j-1]);
			}else{
				break;
			}
		}
	}
}

选择排序

template<typename T>
void selectionSort(T arr[],int n){
	for(int i = 0;i<n;i++){
		int minIndex = i;
		for(int j = i+1;j<n;j++){
			if(arr[j] < arr[minIndex]){
				minIndex = j;
			}
		}
		swap(arr[minIndex],arr[i]);//把a,b交换位置
	}
}

上一节讲到插入排序的最基本的实现,最后测试了插入排序和选择排序所花的时间,发现插入排序虽然可以提前结束第二层循环,但是时间却比选择排序花的更多,看起来插入排序的性能好像不咋的?

介于此,这章节将会讲插入排序的优化,之后就可以明显感觉到对于一个近乎有序的数组,插入排序的性能将会特别高

2.思考

1.首先了解swap函数,对它有了解的同学知道,swap函数交换数组的位置,其实要经过三次赋值,虽然我们提前结束了第二层循环,但是swap这个地方可能需要优化一下

2.如果我们把swap换做一次赋值的话,那么插入排序的性能会得到很好的提升

3.思路

假设有{5,4,8}这样的数组,我们知道角标是0,1,2,0位置元素不动,对于1位置的元素4,首先复制一份值,然后与前一位0位置的值5进行比较,发现5比4要大,那么把5后移一位,现在数组变成[5,5,8],然后将最后保存1位置的元素4赋值给1位置现在的元素5,那么数组变成[4,5,8],往后的类似

4.实战

InsertSort.cpp

#include <iostream>
#include "SortTestHelper.h"
#include "SelectionSort.h"
using namespace std;


template<typename T>
void insertSort(T arr[],int n){
	for(int i = 1;i<n;i++){
		T e = arr[i];
		int j;
		for(j = i;j>0 && arr[j-1] > e;j--){
			arr[j] = arr[j-1];
		}
		arr[j] = e;
	}
}

int main(){
	int n = 100000;
	int* arr = SortTestHelper::generateRandomArray(n,0,100);
	int* arr2 = SortTestHelper::copyArray(arr,n);
	SortTestHelper::testSort("Insert Sort :",insertSort,arr,n);
	SortTestHelper::testSort("Select Sort :",selectionSort,arr,n);
	delete [] arr;
	delete [] arr2;
	return 0;
}

SelectionSort.h

#include <iostream>
#include "Student.h"
#include "SortTestHelper.h"
using namespace std;


/**
 * 选择排序
 */
template<typename T>
void selectionSort(T arr[],int n){
	for(int i = 0;i<n;i++){
		int minIndex = i;
		for(int j = i+1;j<n;j++){
			if(arr[j] < arr[minIndex]){
				minIndex = j;
			}
		}
		swap(arr[minIndex],arr[i]);//把a,b交换位置
	}
}

SortTestHelper.h

#ifndef SORTTESTHELPER_H_
#define SORTTESTHELPER_H_


#include <iostream>
#include <ctime>
#include <cassert>
using namespace std;


namespace SortTestHelper{
	//生成n个元素的随机数组,每个元素的随机范围为[rangeL,rangeR]
	int* generateRandomArray(int n,int rangeL,int rangeR){
		assert(rangeL <= rangeR); //为了程序稳定性,如果rangeL>rangeR,那么程序不会往下执行
		int *arr = new int[n];
		srand(time(NULL));//随机种子,需要导入ctime库
		for(int i = 0;i<n;i++){
			arr[i] = rand() % (rangeR - rangeL + 1) + rangeL; //自己可以动笔算一下
		}
		return arr;
	}


	/**
	 * 检验排序的正确性
	 */
	template<typename T>
	bool isSorted(T arr[],int n){
		for(int i = 0;i<n;i++){
			//注意,如果i=n-2时,实际上会比较arr[n-2]和arr[n-1]的值,此时数组已经比较完毕
			if(i<n-1 && arr[i]>arr[i+1]){
				return false;
			}
		}
		return true;
	}


	/**
	 * 测试排序所需要的时间
	 */
	template<typename T>
	void testSort(string sortName,void(*sort)(T arr[],int n),T arr[],int n){
		clock_t startTime = clock();
		sort(arr,n);
		clock_t endTime = clock();
		assert(isSorted(arr,n));
		cout <<sortName<<" : "<< double(endTime - startTime) /CLOCKS_PER_SEC <<"s" << endl;
		return;
	}


	template<typename T>
	void printArray(T arr[],int n){
		for(int i = 0;i<n;i++)
			cout << arr[i] << " "; //循环打印数组中的元素
		cout << endl;
	}


	int* copyArray(int arr[],int n){
		int* b = new int[n];
		//拷贝数组参数:指针开始的位置;指针结束的位置;目标数组
		copy(arr,arr+n,b);
		return b;
	}


	/**
	 *生成一个近乎有序的数组
	 */
	int* generateNearlyOrderedArray(int n,int swapTimes){
		int* arr = new int[n];
		for(int i = 0;i<n;i++)
			arr[i] = i;


		srand(time(NULL));
		for(int i = 0;i<swapTimes;i++){
			int swapX = rand()%n;
			int swapY = rand()%n;
			swap(arr[swapX],arr[swapY]);
		}
		return arr;
	}


}

#endif /* SORTTESTHELPER_H_ */

运行结果

Insert Sort : : 6.264s
Select Sort : : 12.44s

总结

从结果可以知道,10w级别的测试数据量,对于一个近乎有序的数组,插入排序的性能明显比选择排序要高

意见与建议

如果博友有任何问题或者建议,欢迎留言讨论


数据结构基础系列(9):排序

-
  • 1970年01月01日 08:00

数据结构算法学习总结-慕课网(一)选择排序(从小到大)

数据结构算法学习总结-慕课网(一)选择排序(从小到大)1.说明语法采用c++,不懂得可以去学习一下c++的基本语法2.思路从小到大,也就是后一个比前一个小的话,那么就把二者的顺序交换3.时间复杂度计算...
  • libinbin147256369
  • libinbin147256369
  • 2018-04-15 16:50:09
  • 15

数据结构算法学习总结-慕课网(六)归并排序(从小到大)

数据结构算法学习总结-慕课网(六)归并排序(从小到大)1.回顾上一节讲到冒泡排序,对它有了基本的认识这一节会讲性能比较好的归并排序2.思路如图首先会创建一个与原{2,3,6,8}一模一样的数组temp...
  • libinbin147256369
  • libinbin147256369
  • 2018-04-16 19:55:20
  • 10

数据结构算法学习总结-慕课网(三)插入排序,与选择排序的比较(从小到大)

数据结构算法学习总结-慕课网(三)插入排序,与选择排序的比较(从小到大)1.思路插入排序是将下标为0,1,...的数组的第1个元素开始,第二层循环,如果后一个比前一个小,那么就将后一个与前一个交换位置...
  • libinbin147256369
  • libinbin147256369
  • 2018-04-15 23:24:45
  • 6

数据结构算法学习总结-慕课网(五)冒泡排序,与选择,插入排序的异同(从小到大)

数据结构算法学习总结-慕课网(五)冒泡排序,与选择,插入排序的异同(从小到大)1.回顾上一节讲到了插入排序的优化,了解了插入排序的优势,这一节会讲冒泡排序的实现方式2.思路对于{5,4,2}这样的数组...
  • libinbin147256369
  • libinbin147256369
  • 2018-04-16 11:07:04
  • 4

数据结构算法学习总结-慕课网(九)快速排序(从小到大)

数据结构算法学习总结-慕课网(九)快速排序(从小到大)1.回顾上一节降到了自底向上的归并排序这一节将讲一个性能很高的排序,快速排序2.分析快速排序的思想是首先取数组的第一个元素,记为v,找到一个合适的...
  • libinbin147256369
  • libinbin147256369
  • 2018-04-18 16:58:30
  • 7

数据结构算法学习总结-慕课网(七)归并排序优化(自顶向下,从小到大)

数据结构算法学习总结-慕课网(七)归并排序优化(自顶向下,从小到大)1.回顾上一节讲到归并排序,了解了归并排序的基本实现这一节将讲归并排序的两个优化2.思路1.归并排序最后归并的时候,左边和右边都是有...
  • libinbin147256369
  • libinbin147256369
  • 2018-04-17 11:32:22
  • 1

重学C++ 对数组进行插入排序

#include using std::cout; using std::endl; #include using std::setw; int main() { const ...
  • niu91
  • niu91
  • 2013-04-18 20:51:42
  • 1316

慕课网原来的免费路径网址,快收藏。

1、Java工程师 http://www.imooc.com/course/programdetail/pid/31 2、Web前端工程师 http://www.imooc.com/course/p...
  • u012687612
  • u012687612
  • 2017-02-17 15:30:00
  • 897
收藏助手
不良信息举报
您举报文章:数据结构算法学习总结-慕课网(四)插入排序的优化(从小到大)
举报原因:
原因补充:

(最多只允许输入30个字)