C++ implements seven sorting algorithms

Kind of sort

According to whether all the records to be sorted are placed in memory during the sorting process , sorting is divided into inner sorting and outer sorting.

Internal sorting: All records to be sorted are placed in memory.

External sorting: because the number of sorting records is too large to be placed in the memory, the sorting process needs to exchange data between internal and external memory multiple times.

According to whether the records to be sorted are compared during the sorting process, it can be divided into comparative sorting and non-comparative sorting.

Comparison sort: bubble sort, selection sort, insertion sort, merge sort, heap sort, quick sort, etc.

Non-comparative sorting: radix sorting, bucket sorting, counting sorting, etc.


Three indicators that affect the sorting algorithm

The sorting algorithm we usually refer to is the internal sorting algorithm . For internal sorting, it is mainly affected by three aspects. They are: time performance, auxiliary space (spatiality), and algorithm complexity.

1. Indicator 1 - time performance

In inner sorting, there are two main operations: comparison and movement. Comparison is a comparison between keywords, and movement refers to the movement of records from one location to another. Therefore, the time overhead of a sorting algorithm is an important indicator of its quality.

2. Indicator 2 - auxiliary space

Auxiliary space refers to other storage space required to execute the algorithm in addition to the storage space occupied by the sorting, which is another criterion to measure the quality of the algorithm.

3. Indicator 3 - the complexity of the algorithm

The algorithmic complexity here is not the time complexity. According to the complexity of the algorithm, it can be divided into two categories, simple algorithm and improved algorithm.

Simple Algorithms: Bubble, Select, Insert

Improved algorithm: Hill, heap, merge, quick sort


Structures and other functions

Structure definition

typedef int ElemType;
#define MAXSIZE 10
#define N 10 
typedef struct {
    
    
	ElemType data[MAXSIZE];//存储的数据元素 
	int length;// 线性表当前长度
}SqList;//线性表 

exchange function

/*交换线性表L中下标为i和j的元素*/
void Swap(SqList &L,int i,int j) {
    
    
	int temp=L.data[i];
	L.data[i]=L.data[j];
	L.data[j]=temp;
}

Initialize the linear table

 /* 初始化顺序线性表 */
bool InitList(SqList &L) 
{
    
     
    L.length=MAXSIZE;
    return true;
}

output the elements in the linear list

 /*输出线性表中的元素*/
 void PrintList(const SqList &L){
    
    
 	
 	for(int i=0;i<L.length;i++)
 		cout<<L.data[i]<<" ";
	cout<<endl;
 }
 

1. Bubble sort

Bubble sort (Bubble Sort), a kind of exchange sort, the basic idea is: compare the keywords of adjacent records two by two, and exchange them if they are in reverse order until there are no records in reverse order.

For the array storing the original data, perform multiple scans in the direction from front to back, and each scan becomes one pass. When the size of the two data is found to be inconsistent with the bit sequence, it is exchanged. After each pass is sorted, the Put the largest number at the end. The number of comparisons in each pass is gradually reduced, because each comparison sinks the maximum number in each pass to the bottom.

Features: In ascending sorting, each round of comparison will sink the largest number to the bottom, so the number of mutual comparisons in each round will be one less than the previous round.

Sort the N numbers through N-1 times (rounds), compare the ascending sort, the large sink, and the descending sort, the small sink.

Bubble Sort Basic Edition

/*
 	冒泡排序初级版
 	不算是标准的冒泡排序算法,因为不满足
	"两两比较相邻记录的" 的冒泡排序思想。
	
	算法思路:
		让每一个数据元素和后一个数据元素
	进行比较,如果大则进行交换,在第一趟
	比较,最后一个元素一定是最大值。 
	
	
 */
 void EasyBubbleSort(SqList &L){
    
    
 	for(int i=0;i<L.length-1;i++)//n个数比较 n-1趟 
 		for(int j=0;j<L.length-i;j++)//比较n-i次 
 			if(L.data[j]>L.data[j+1])
			 	Swap(L,j,j+1) ;//交换 L->data[i]与 L->data[j]的值 
	
 }

Ordinary Bubble Sort

/*冒泡排序*/
 void BubbleSort(SqList &L) {
    
    
 	for(int i=0;i<L.length-1;i++)
 		for(int j=L.length-1;j>=i;j--)//将L.data[i] 元素归位 
 			if(L.data[j]>L.data[j+1])//相邻的练个元素反序时 
 				Swap(L,j,j+1);//将 L->data[i]与 L->data[j]的值 交换
 }

Improved Bubble Sort

/*
 	冒泡排序改进
 	假如序列{2,1,3,4} 
 	如果比较第一二次之后,在之前
	的冒泡排序还会一直比下去,从i=1一直
	执行到i=3,数量越大,则时间耗得越长,
	为了避免这种情况,设计了一个标志位。
	在每一次交换过后,置为1,循环判断如果为1则执行
	否则跳过本趟比较。 
 */
 void BubbleSortImprove(SqList &L){
    
    
 	bool flag= true;
 	for(int i=0;i<L.length-1&&flag;i++){
    
     
 		flag=false;
 		for(int j=L.length-1;j>=i;j--){
    
    
 			if(L.data[j-1]>L.data[j]){
    
    
 				Swap(L,j-1,j);
 				flag=true;//如果有数据交换,则flag为true 
			 }
		 }
	 }
 	
 }

The total time complexity of bubble sorting is O(n^2)


2. Simple selection sort

Algorithm idea: Select the record with the smallest keyword from n-i+1 records by comparing ni times of keywords, and exchange it with the i-th (1<=i<=n) record.

This simple comparison method to select the element with the smallest keyword is the origin of the name of the simple selection sort.

 /*简单选择排序*/
 void SelectSort(SqList &L){
    
    
 	
 	for(int i=0;i<L.length;i++){
    
    
 		int min=i;//将当前的下标定义为最小值下标
		for(int j=i+1;j<L.length;j++) {
    
    
		 	
		 	if(L.data[min]>L.data[j]){
    
    //如果当前的值比下标为min中的还小 
		 		min=j;//把这个下标给min 
			 }
		}
		if(i!=min) //如果min与当前i值不想等,说明找到最小值 
			Swap(L,i,min);
	 }
 }
 

The time complexity of simple selection sort and bubble sort is O(n^2), but the performance of simple selection sort is still slightly better than bubble sort.


3. Insertion sort

Direct insertion sort (using the first element of the array as a buffer)

Algorithm idea: Insert a record into the ordered list that has been sorted, so as to obtain a new ordered list with the number of records increased by 1.

/*
 	直接插入排序:
 	第一种写法, 数组的第一个元素不存储,起到一个缓冲器的作用 
	线性表中的第一个元素在这里起到哨兵的作用 
	当前元素如果比后一个元素小,那么将当前元素设置为哨兵,
	再把当前元素之前的所有元素与哨兵进行比较,如果比哨兵小,
	那么哨兵为这个元素,反之,则进行交换。
	所以,最后一次比较,哨兵是最后一轮的最小元素。 
 */
 void InsertSort(SqList &L) {
    
    
 	int i,j;
 	for( i=2;i<L.length;i++){
    
    
 		if(L.data[i]<L.data[i-1]){
    
    
 			L.data[0]=L.data[i];//设置哨兵,哨兵为每轮比较的最小元素 
 			for( j=i-1;L.data[j]>L.data[0];j--){
    
    
 				L.data[j+1]=L.data[j];//记录后移 这里的j+1其实是i 
			}
			L.data[j+1]=L.data[0];//交换元素,把哨兵插入到正确的位置 
		 }
	 }
 }
 

If the sorting records of this writing method are random, then the average number of comparisons and moves ≈ (n 2)/4, and the time complexity is O(n 2), but the performance of direct insertion sorting is slightly better than that of bubbling and selection sorting .

Algorithm idea: Insert the beginning element a[i] (1<=i<=n-1) of the unordered area into the appropriate position in the ordered area a[0...i-1], so that a[0...i ] becomes a new ordered area.

Insertion sort directly (exchange directly)

 /*
 	直接插入排序
	第二种写法,不采用数组第一个元素为缓冲器,
	默认第一个元素是有序的,直接进行交换 
	 
 */
 void InsertSort2(SqList &L) {
    
    
 	for(int i=1;i<L.length;i++){
    
    
 		int key=L.data[i];
 		int j=i-1;
 		while(j>=0&&L.data[j]>key){
    
    //定位,当前一个元素比key大  
 			L.data[j+1]=L.data[j];//插入,大记录后移,小记录前移 
 			j--;
		 } 
		 //如果j<0,则说明依次与前面进行比较比完了,此时是data[0]=key; 
		 //如果data[j]<key,则不比较data[j],key的值不变。 
		L.data[j+1]=key; 
	 }
 }

Explanation: The ordered area generated in each pass of the second writing method is not necessarily the global ordered area, that is to say, the elements in the ordered area are not necessarily placed in the final position. Putting it in its final position becomes homing.

Binary Insertion Sort

Algorithm idea: Insert the beginning element a[i] (1<=i<=n-1) of the unordered area into the ordered area a[0...i-1], and use the method of sequential comparison, because the ordered area The elements are in order. Here, we use the method of binary search to find the insertion position in a[0...i-1], and then move the elements, which is also called binary insertion sorting.

/*
 	折半插入排序
 	利用二分查找定位,再进行插入排序 
 */
 void BinInsertSort(SqList &L){
    
    
 	int i,j,low,mid,high;
 	for( i=1;i<L.length;i++){
    
    
 		if(L.data[i]<L.data[i-1]){
    
    
 			int tmp=L.data[i];
 			low=0;
 			high=i-1;
 			while(low<=high){
    
    //在L.data[low...high] 中查找插入的位置 
 				mid=(low+high) /2;//取中间位置 
 				if(tmp<L.data[mid])
					high=mid-1;//插入点在左半区间
				else
					low=mid+1;//插入点在右半区间  
			 }
			for(j=i-1;j>=high+1;j--) {
    
    
				L.data[j+1]=L.data[j];
			}
			L.data[high+1]=tmp;
		 }
	 }
 	
 }

Compared with direct insertion sort, half sorting does not improve the performance of moving elements, but only reduces the number of comparisons of keywords. In terms of average performance, half search is better than sequential search, so half insertion sort is also better than direct insertion sort. The space complexity of insertion sort is O(1).


4. Quick Sort

It is improved by bubble sorting. The basic idea is: randomly select an element (usually the first element) among the n elements to be sorted as the benchmark, and after putting the element in an appropriate position, the data sequence is divided by this element two parts. The element smaller than the element is placed in front, the element larger than the element is placed in the back, and the element is placed in the middle of the two elements (become the element homing). This process is called a quick sort (also called a pass division).

Then repeat the above process for the two generated parts, until there is only one element in each part or it is empty. To put it simply, each division puts the first element in the table into a suitable position, divides the table into two, and continues this division recursively on the sub-table until the length of the divided sub-table is 1 or 0.

 /* 
 	快排 
 */
 void QuickSort(SqList &L,int l,int r){
    
    
 	//判断合法性 递归结束 
 	if(l>=r) return ;
 	
 	int key=L.data[l],i=l-1,j=r+1;
 	while(i<j){
    
    
 		//保证左边的<key,右边的>key 
 		do i++;while(L.data[i]<key) ;
 		do j--;while(L.data[j]>key);
 		if(i<j)Swap(L,i,j);
	 }
	 QuickSort(L,l,j);
	 QuickSort(L,j+1,r);
 }

5. Merge sort

Basic idea:

The sorting method implemented by using the idea of ​​merging, assuming that the initial sequence contains n records, it can be regarded as n ordered subsequences, the length of each subsequence is 1, and then merged in pairs, you can get ⌈n/ 2⌉ (⌈x⌉ represents the smallest integer not less than x) ordered subsequences with a length of 2 or 1, and then merge them two by two, and repeat this until an ordered sequence with a length of n is obtained.

/*
 	归并排序 
*/
int temp[MAXSIZE];
void MergeSort(SqList &L, int l,int r){
    
    
	if(l>=r)return ;
	//划分区间
	int mid=(l+r)/2;
	MergeSort(L,l,mid);
	MergeSort(L,mid+1,r);	
	
	int k=0,i=l,j=mid+1;	
	//把两边区间最小的数存入temp中 
	while(i<=mid&&j<=r) {
    
    
		if(L.data[i]<=L.data[j])
			temp[k++]=L.data[i++];
		else
			temp[k++]=L.data[j++];
	}
	
	//把两边任一剩下的数存入temp中
	while(i<=mid) 
		temp[k++]=L.data[i++];
	while(j<=r)
		temp[k++]=L.data[j++];
		
	//从左边开始把temp中的数放回至a中 
	for(i=l,j=0;i<=r;i++,j++)	
		L.data[i]=temp[j];
}
 

Summary of the performance of the seven algorithms

sorting method time complexity space complexity stability Complexity
average case worst case best case
Bubble Sort O(n^2) O(n^2) O(n) O(1) Stablize Simple
simple selection sort O(n^2) O(n^2) O(n^2) O(1) unstable Simple
direct insertion sort O(n^2) O(n^2) O(n) O(1) Stablize Simple
Binary Insertion Sort O(n^2) O(n^2) O(n) O(1) Stablize Simple
quick sort O(nlogn) O(n^2) O(nlogn) O(logn) unstable more complex
two-way merge sort O(nlogn) O(nlogn) O(nlogn) O(n) Stablize more complex

Guess you like

Origin blog.csdn.net/qq_42242452/article/details/124641223