Use C language to sort students' grades (exchange sorting algorithm)

1. Exchange sort

The so-called exchange refers to swapping the positions of the two records in the sequence according to the comparison result of the two element keys in the sequence. There are many sorting algorithms based on exchange. This article mainly introduces bubble sorting and quick sorting.

The previous blog learned insertion sorting, and today it is exchange sorting, which and insertion sorting are both internal sorting

2. Bubble sort

1. Basic idea

The basic idea of ​​bubble sorting is: compare the values ​​of adjacent elements two by two from the back to the front (or from the front to the back), and if they are in reverse order (ie A[i-1]>A[i]), exchange them until The sequences are compared. We call it the first pass of bubbling, and the result is that the smallest element is swapped to the first position of the column to be sorted (or the largest element is swapped to the last position of the column to be sorted), and the element with the smallest keyword is like a bubble Generally, it gradually "floats" upward until it reaches the "water surface" (or the largest element of the keyword sinks to the bottom of the water like a stone). In the next bubbling, the minimum element determined in the previous bubbling will no longer participate in the comparison, and the result of each bubbling is to put the minimum element (or maximum element) in the sequence in the final position of the sequence...so do n-1 at most A single bubbling can sort all the elements.

2. Example

The following is a process of bubble sorting, when the first bubbling: 27<49, no exchange; 13<27, no exchange; 76> 13, exchange; 97>13, exchange; 65>13, exchange; 38> 13, exchange; 49>13, exchange. After passing through the first bubbling pass, the smallest element has been swapped to the first position, which is also its final position. The same method is used to sort the remaining subsequences in the second bubbling pass, and so on. After the fifth pass, there is no exchange, indicating that the table is in order, and the bubble sorting ends.

insert image description here

3. Performance analysis

The performance analysis of bubble sort is as follows:

  • Space Efficiency: Only a constant number of auxiliary units are used, resulting in a space complexity of 0(1).

  • Time efficiency: When the initial sequence is in order, it is obvious that the flag is still false after the first bubbling (there is no element exchange in this pass), thus directly jumping out of the loop, the number of comparisons is n-1, and the number of moves is 0, so the best case The time complexity below is O(n); when the initial sequence is in reverse order, n-1 sorting is required, and the i-th sorting needs to compare ni keywords, and elements must be moved 3 times after each comparison to swap element positions. In this situation,

    Number of comparisons = ∑ 1 t ( n − 1 ) \sum_1^t (n-1)1t(n1)= n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n1),Number of moves = ∑ 1 t 3 ( n − i ) \sum_1^t 3(ni)1t3(ni) = 3 n ( n − 1 ) 2 \frac{3n(n-1)}{2} 23 n ( n 1 )

    Thus, the time complexity in the worst case is O(n 2 ), and the average time complexity is 0(n 2 ).
    Stability: Since i>j and A[i]=A[j], there will be no exchange, so bubble sorting is a stable sorting method.

3. Quick Sort

1. Basic idea

The basic idea of ​​quick sorting is based on the divide and conquer method: in the list to be sorted L1...n], an element pivot is taken as the pivot (or called the benchmark, usually taking the first element), and the list to be sorted is divided by one-way sorting For independent two parts L[...k-1] and L[k+1...n], so that all elements in L[...k-1] are less than pivot, all elements in L[k1...n] are greater than or equal to pivot, the pivot is placed on its final position L(k), this process is called a division. Then recursively repeat the above process for the two sublists, until there is only one element or empty in each part, that is, all elements are placed in their final positions.

2. Example

A quick sorting process is a process of alternate searching and exchanging. The following is an example to introduce. There are two pointers i
and j, the initial values ​​are low and high respectively, and the first element 49 is taken as the pivot and assigned to the variable pivot .

  • The pointer j searches forward from high to find the first element 27 smaller than the pivot, and swaps 27 to the position pointed by i.
    insert image description here

  • Pointer i searches backward from low to find the first element 65 that is larger than the pivot, and swaps 65 to the position pointed to by j.
    insert image description here

  • The pointer j continues to search forward to find the element 13 smaller than the pivot, and exchange 13 to the position pointed by i.
    insert image description here

  • Use the same method to quickly sort each subsequence. If there is only one element in the sequence to be sorted, it is obviously in order.

insert image description here

3. Performance analysis

The performance analysis of the quick sort algorithm is as follows:

  • Space efficiency: Since quicksort is recursive, a recursive work stack is needed to save the necessary information for each layer of recursive calls, and its capacity is consistent with the maximum depth of recursive calls. In the best case, it is O(log 2 n); in the worst case, because n-1 recursive calls are required, the depth of the stack is O(n); on average, the depth of the stack is O(log 2 n ).
  • Time efficiency: The running time of quick sort is related to whether the partition is symmetrical. The worst case of quick sort occurs when two areas contain n-1 elements and 0 elements respectively. If this maximum asymmetry occurs in each On layer recursion, that is, when the initial sorting table is basically ordered or basically reversed, the time complexity in the worst case is 0(n 2 ).
  • Quicksort is an unstable algorithm.

4. Implementation of the core algorithm

1. Bubble sort

//冒泡排序
void BubbleSore(SqList &L){
    
    
	Elemtype temp;
	for(int i=0;i<L.length;i++){
    
                      //每一趟确定第一个数据的位置
		bool flag=false;                         //每一趟是否发生交换的标志
		for(int j=L.length-1;j>i;j--){
    
                  //从最后开始冒泡
			if(L.data[j-1].grade>L.data[j].grade){
    
    
				temp=L.data[j];
				L.data[j]=L.data[j-1];
				L.data[j-1]=temp;
				flag=true;              //表示发生交换
			}
		}
		if(flag==false)
			return;
	}
}

2. Quick Sort

//划分函数
int Partition(SqList &L,int low,int high){
    
    
	Elemtype pivot=L.data[low];
	while(low<high){
    
    
		while(low<high && L.data[high].grade>=pivot.grade)  high--;
		L.data[low]=L.data[high];
		while(low<high && L.data[low].grade<=pivot.grade)  low++;
		L.data[high]=L.data[low];
	}
	//出这个while循环的条件就是low=high
	L.data[low]=pivot;
	return low;
}

//快速排序
void QuickSort(SqList &L,int low,int high){
    
    
	if(low<high){
    
    
		int pivotpos=Partition(L,low,high);         //开始划分
		QuickSort(L,low,pivotpos-1);               //依次对两个子表进行划分
		QuickSort(L,pivotpos+1,high);
	}
}

Five. C language display

/*我们今天的主角插入排序是基于查找算法来的,所以我们还是利用线性表来进行模拟*/

/*为了便于我们后面演示希尔排序,所以我们采用顺序存储结构*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MaxSize 50                //这里只是演示,我们假设这里最多存五十个学生信息

//定义学生结构
typedef struct {
    
    
	char name[200];              //姓名
	int  grade;               //分数,这个是排序关键字
} Elemtype;

//声明使用顺序表
typedef struct {
    
    
	/*这里给数据分配内存,可以有静态和动态两种方式,这里采用动态分配*/
	Elemtype  *data;            //存放线性表中的元素是Elemtype所指代的学生结构体
	int length;                 //存放线性表的长度
} SqList;						//给这个顺序表起个名字,接下来给这个结构体定义方法

//初始化线性表
void InitList(SqList &L){
    
    
	/*动态分配内存的初始化*/
	L.data = (Elemtype*)malloc(MaxSize * sizeof(Elemtype));  //为顺序表分配空间
	L.length = 0;                                            //初始化长度为0
}

//求表长函数
int Length(SqList &L){
    
    
	return L.length;
}

//求某个数据元素值
bool GetElem(SqList &L, int i, Elemtype &e) {
    
    
	if (i < 1 || i > L.length)
		return false;         //参数i错误时,返回false
	e = L.data[i - 1];      //取元素值
	return true;
}

//输出线性表
void DispList(SqList &L) {
    
    
	if (L.length == 0)
		printf("线性表为空");
	//扫描顺序表,输出各元素
	for (int i = 0; i < L.length; i++) {
    
    
		printf("%s        %d", L.data[i].name,  L.data[i].grade);
		printf("\n");
	}
	printf("\n");
}

//插入数据元素
bool ListInsert(SqList &L, int i, Elemtype e) {
    
    
	/*在顺序表L的第i个位置上插入新元素e*/
	int j;
	//参数i不正确时,返回false
	if (i < 1 || i > L.length + 1 || L.length == MaxSize)
		return false;
	i--;                //将顺序表逻辑序号转化为物理序号
	//参数i正确时,将data[i]及后面的元素后移一个位置
	for (j = L.length; j > i; j--) {
    
    
		L.data[j] = L.data[j - 1];
	}
	L.data[i] = e;      //插入元素e
	L.length++;         //顺序表长度加1
	return true;
	/*平均时间复杂度为O(n)*/
}

//冒泡排序
void BubbleSore(SqList &L){
    
    
	Elemtype temp;
	for(int i=0;i<L.length;i++){
    
                      //每一趟确定第一个数据的位置
		bool flag=false;                         //每一趟是否发生交换的标志
		for(int j=L.length-1;j>i;j--){
    
                  //从最后开始冒泡
			if(L.data[j-1].grade>L.data[j].grade){
    
    
				temp=L.data[j];
				L.data[j]=L.data[j-1];
				L.data[j-1]=temp;
				flag=true;              //表示发生交换
			}
		}
		if(flag==false)
			return;
	}
}

//划分函数
int Partition(SqList &L,int low,int high){
    
    
	Elemtype pivot=L.data[low];
	while(low<high){
    
    
		while(low<high && L.data[high].grade>=pivot.grade)  high--;
		L.data[low]=L.data[high];
		while(low<high && L.data[low].grade<=pivot.grade)  low++;
		L.data[high]=L.data[low];
	}
	//出这个while循环的条件就是low=high
	L.data[low]=pivot;
	return low;
}

//快速排序
void QuickSort(SqList &L,int low,int high){
    
    
	if(low<high){
    
    
		int pivotpos=Partition(L,low,high);         //开始划分
		QuickSort(L,low,pivotpos-1);               //依次对两个子表进行划分
		QuickSort(L,pivotpos+1,high);
	}
}

int main(){
    
    
	SqList L;
	Elemtype stuents[10]={
    
    {
    
    "张三",649},{
    
    "李四",638},{
    
    "王五",665},{
    
    "赵六",697},{
    
    "冯七",676},
		{
    
    "读者",713},{
    
    "阿强",627},{
    
    "杨曦",649},{
    
    "老六",655},{
    
    "阿黄",604}};
	//这一部分忘了的请回顾我的相关博客
	printf("初始化顺序表并插入开始元素:\n");
	InitList(L);         //这时是一个空表,接下来通过插入元素函数完成初始化
	for (int i = 0; i < 10; i++)
		ListInsert(L, i + 1, stuents[i]);
	DispList(L);
	/*printf("根据分数进行冒泡排序的结果为:\n");
	BubbleSore(L);
	  DispList(L);*/
	printf("根据分数进行快速排序的结果为:\n");
	int low=0;
	int high=L.length-1;
	QuickSort(L,low,high);
	DispList(L);
}





6. Running results

1. Bubble sort

insert image description here

2. Quick Sort

insert image description here

Guess you like

Origin blog.csdn.net/weixin_51496226/article/details/131483682