首页 > 其他分享 >《基础数据结构-排序》之交换排序

《基础数据结构-排序》之交换排序

时间:2023-02-11 17:23:54浏览次数:50  
标签:std head 数据结构 交换 high split 排序 data low

PS:要转载请注明出处,本人版权所有。

PS: 这个只是基于《我自己》的理解,

如果和你的原则及想法相冲突,请谅解,勿喷。

前置说明

  本文作为本人csdn blog的主站的备份。(BlogID=060)
  本文发布于 2018-05-10 11:21:42,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=060)

环境说明

  MEM:2GB

  CPU:Intel® Core™ i5-7400 CPU @ 3.00GHz × 4

  SYSTEM:Linux 4.13.0-38-generic #43~16.04.1-Ubuntu SMP Wed Mar 14 17:48:43 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux(虚拟机)

  测试数据(100000条数据,数据范围1-100000)下载链接:https://download.csdn.net/download/u011728480/10399194

前言


  此系列大概会有三类文章,包括我在学校不太掌握的三种类型的相关算法,分别为排序、树、图中的基础算法。这里主要对这些算法进行一个巩固,期望使自己的相关技术有一定的提高。

  排序算法要解决的问题是:把一系列已存在的数据(乱序),按照一定规律(有序)进行存放。我们常见的就是数字的按照其大小进行排序。排序按照其实现的核心原理分为约4中类型:交换排序、插入排序、选择排序和归并排序。下面依次对这些排序进行说明和总结。

  ps:上面内容都是扯淡,大佬直接忽略。





交换排序


  交换排序有两种常见算法:冒泡排序和快速排序



冒泡排序

  就是遍历,交换。把符合某规律的数据元素交换到数据顶端(有条件的末端),重复此过程,直到数据序列有序为止。

  使用上文数据进行排序,结果如图:

rep_img

  平均时间复杂度:O(n ^ 2)

  空间复杂度:O(1)

  实现代码(下面算法是未做任何优化的,一种优化方法为:如果为发生数据交换,则数据有序且退出整个循环):

/*

worst time:
surrounding loop=n-1
compare=n(n-1)/2  (等差数列求和,1,2....n-1)
exchange=3n(n-1)/2 (等差数列求和,1,2....n-1,每次交换3次)

best time:(针对此代码,未优化)
surrounding loop=n-1
compare=n(n-1)/2
exchange=0


average-time:O(n ^ 2)
space:O(1)

*/


#include <iostream>
#include <fstream>
#include <chrono>
#include <string>
#include <assert.h>
#include <functional>


template <typename T, typename T1>
int bubble_sort(T * const head, const T1 &len, std::function<void(T&, T&)> swap_func = nullptr){
//int bubble_sort(T * const head, const T1 &len, void (*swap_func)(T&,T&) = nullptr){

	//data_len data_tmp must init for type deduction
	auto data_len = len;//
	auto data_tmp = *head;//
	auto i = len,j = len;
	//len-1 traverse
	for (j = 1; j < data_len; j ++){//n-1
		
		for (i = 0; i < data_len -j; i ++){

			if ( nullptr != swap_func )
				swap_func(*(head+i), *(head+i+1));
			else{
		
				if ( *(head+i) > *(head+i+1) ){
			
					data_tmp = *(head+i);
					*(head+i) = *(head+i+1);
					*(head+i+1) = data_tmp;
				}
			}
		}
	} 
	return 0;
}

#define DATA_LEN 100000

int main(int argv, char * argc[]){
	
	long * buffer;
	std::filebuf *pbuf;  
	std::ifstream in;
	std::ofstream out;
	in.open("data.txt");
	assert(in.is_open());
	long idx = 0;
	
	buffer = new long[DATA_LEN];

	std::string data;
	for ( ; idx < DATA_LEN; idx++ ){
			
		getline(in, data);	
		*(buffer+idx) = atol(data.c_str());
	}
	in.close();

	std::chrono::time_point<std::chrono::high_resolution_clock> p0 = std::chrono::high_resolution_clock::now();
	bubble_sort(buffer, DATA_LEN);
 	std::chrono::time_point<std::chrono::high_resolution_clock> p1 = std::chrono::high_resolution_clock::now();
	std::cout << "stitch high_resolution_clock time:" << (float)std::chrono::duration_cast<std::chrono::microseconds>(p1 - p0).count() / 1000 << "ms" << std::endl;
    	
	out.open("bubble_sort.txt");
	assert(out.is_open());
	
	for (idx = 0 ; idx < DATA_LEN; idx++ ){
			
		out<<*(buffer+idx);
		out<<"\n";
	}
	out.close();
	
  	delete []buffer;  
	return 0;
}



快速排序

  选定一个基准数(一般为第一个数),然后把小于此数的数放到其左边,大于此数放到右边,这时,此数组被分为了两组。然后分别对这两组数进行同样的操作,直到数无法继续分组为止。

  使用上文数据进行排序,结果如图:

rep_img

  平均时间复杂度:O(nlog(n))
  空间复杂度:O(log(n)~n)
  实现代码:

/*
worst time:O(n^2)
(每次我们指定的分割数是数列里面最大,或者最小,这样导致只会把一个数放到了正确的位置,类似选择排序或者冒泡排序,由于是递归调用,可参考二叉树结构分析)

(此时二叉树结构为最不平衡的二叉树,退化为一条线)
compare=n(n-1)/2(第一次比较n-1,第二次比较n-2  ...   1)
exchange=n(n-1)/2

best time: nlog(n) (注意,取的是数量级)
(参考平衡二叉树)
tree-deepth=log(n)
compare=(n/2)(1-(0.5^n))/(1-0.5) (等比数列求和,n/2 , n/4, ... n/2^n)
exchange=0


average-time:O(nlog(n)) (这里要用什么来证明一下,我搞不清楚原理了)
space:O(log(n)~n)(最坏时间为n(递归深度n),最优时间为log(n)(递归深度log(n)))

*/


#include <iostream>
#include <fstream>
#include <chrono>
#include <string>
#include <assert.h>
#include <functional>


template <typename T, typename T1>
int quick_sort(T * const head, T1 low, T1 high, std::function<T1(T * const, T1 , T1 )> split_func){
//int bubble_sort(T * const head, const T1 &len, void (*swap_func)(T&,T&) = nullptr){

	//split must init for type deduction
	auto split = low;
	if (low < high){
		
		split =  split_func(head, low, high);//split into two arrary and get split val 
		quick_sort(head, low, split-1, split_func);//deal < split 
		quick_sort(head, split+1, high, split_func);//deal > split 
		
	}
		
	
	return 0;
}


long int split_func_imp(long int * const head, long int low, long int high){
	
	auto split_val = head[low];
	for (; low < high ;){
		
		for ( ; low < high && head[high] <= split_val ; )
			high--;
		head[low] = head[high];
		
		for ( ; low < high && head[low] >= split_val ; )
			low++;
		head[high] = head[low];
	}
	head[low] = split_val;
	return low;
}


#define DATA_LEN 100000

int main(int argv, char * argc[]){
	
	long * buffer;
	std::filebuf *pbuf;  
	std::ifstream in;
	std::ofstream out;
	in.open("data.txt");
	assert(in.is_open());
	long idx = 0;
	
	buffer = new long[DATA_LEN];

	std::string data;
	for ( ; idx < DATA_LEN; idx++ ){
			
		getline(in, data);	
		*(buffer+idx) = atol(data.c_str());
	}
	in.close();
	long low = 0;
	long high = DATA_LEN;
	std::function<long int (long int * const, long int , long int )> func = split_func_imp;
	std::chrono::time_point<std::chrono::high_resolution_clock> p0 = std::chrono::high_resolution_clock::now();
	quick_sort(buffer, low, high, func);
 	std::chrono::time_point<std::chrono::high_resolution_clock> p1 = std::chrono::high_resolution_clock::now();
	std::cout << "stitch high_resolution_clock time:" << (float)std::chrono::duration_cast<std::chrono::microseconds>(p1 - p0).count() / 1000 << "ms" << std::endl;
    	
	out.open("quick_sort.txt");
	assert(out.is_open());
	
	for (idx = 0 ; idx < DATA_LEN; idx++ ){
			
		out<<*(buffer+idx);
		out<<"\n";
	}
	out.close();
	
  	delete []buffer;  
	return 0;
}




后记


  无

参考文献




打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
qrc_img

PS: 请尊重原创,不喜勿喷。

PS: 要转载请注明出处,本人版权所有。

PS: 有问题请留言,看到后我会第一时间回复。

标签:std,head,数据结构,交换,high,split,排序,data,low
From: https://www.cnblogs.com/Iflyinsky/p/17112144.html

相关文章