排序总结

本文详细介绍了五种经典的排序算法:插入排序、希尔排序、堆排序、归并排序及快速排序。每种算法均从思想、时间复杂度、稳定性等方面进行了阐述,并通过示例演示了排序过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 插入排序

1,思想:将第 i 个记录插入到前面 i-1 个已经排序好的序列之中。

2,时间复杂度 O(n^2),空间复杂度 O(1)。

3,稳定性:稳定。

4,过程分析

     初始:    34    8    64   51   32   21

    第一趟: 8    34   64    51   32   21

    第二趟     8    34   64    51   32   21

    第三趟     8    34   51    64   32   21

    第四趟     8    32   34    51   64   21

    第五趟     8    21   32   34    51  64

5,伪码:

void insertionSort(vector<int> A){  
	for (int i = 1; i < A.size(); ++i){
		int tmp = A[i];
		int j = i;
		for (; j >0 && A[j - 1]>tmp; j--)
			A[j] = A[j - 1];
		A[j] = tmp;
	}
}

二、希尔排序

1,思想:将待排序记录序列分割为若干稀疏的子序列,分别进行插入排序。

2,时间复杂度 O(n^(3/2)),空间复杂度 O(1)。

3,稳定性:不稳定。{2,4,1,2},2和1是一组,4和2是一组,进行希尔排序后,两个2的相对位置发生了变化。

4,过程分析: 

     初始:          81 94  11  96  12  35  17  95  28  58  41  75  15

  第一趟 d=5     35  17  11  28  12  41  75  15  96  58  81  94  95

  第二趟 d=3     28  12  11  35  15  41  58  17  94  75  81  96  95

  第三趟 d=1     11  12  15  17  28  35  41  58  75  81  94  95  96

5,伪码

void shellSort(vector<int> A){
	int N = A.size();
	int i, j, Incremnet;
	int tmp;
	for (Incremnet = N / 2; Incremnet > 0; Incremnet /= 2){
		for (int i = Incremnet; i < N; ++i){
			tmp = A[i];
			for (j = i; j >= Incremnet; j -= Incremnet){
				if (tmp < A[j - Incremnet])
					A[j] = A[j - Incremnet];
				else
					break;
			}
			A[j] = tmp;
		}
	}
}

三、堆排序

1,思想:将待排序的关键字存放在数组中,将这个数组看成是一棵完全二叉树的顺序表示,每个结点表示一个记录,第一个记录作为二叉树的根,以下各记录依次逐层从左到右顺序排列。

2,时间复杂度 O(nlogn),空间复杂度 O(1)。

3,稳定性:不稳定排序。{5,5,3}

4,过程分析

      对于堆排序,首先建初堆,再初始化大根堆,把栈顶元素和堆尾元素交换,最后对其前面的几个元素重新进行堆调整。

      http://www.cnblogs.com/chengxiao/p/6129630.html

5,伪码

#define leftChild(i) (2*(i)+1)
void percDown(vector<int> A, int i,int N){
	int child;
	int tmp;
	for (tmp = A[i]; leftChild(i) < N; i = child){
		child = leftChild(i);
		if (child != N - 1 && A[child + 1]>A[child]) child++;
		if (tmp < A[child])
			A[i] = A[child];
		else
			break;
	}
	A[i] = tmp;
}
void heapSort(vector<int> A, int N){
	int i;
	for (i = N / 2; i >= 0; i--)
		percDown(A, i,N);
	for (i = N - 1; i > 0; i--){
		swap(A[0], A[i]);
		percDown(A, 0,i);
	}
}

四、归并排序

1,思想:将 n  个记录看成 n  个有序的子序列,每一个子序列的长度为 1,然后两两归并,得到 n/2 个长度为 2 的有序子序列,如此重复,直到得到一个长度为 n  的有序序列为止。

2,时间复杂度 O(nlogn)  , 空间复杂度 O(n)

3,稳定性:稳定排序。

4,过程分析

 初始         12  2  16  30  8  28  4  10  20  6  18

第一趟     (2  12)(16  30)(8  28)(4 10)(6  20)(18)

第二趟      (2  12  16  30)(4  8  10  28)(6  18  20)

第三趟      (2  4  8  10  12  16  28  30)(6  18  20)

第四趟       2  4  6  8  10  12  16  18  20  28  30

5,伪码

void mSort(vector<int> A, vector<int> tmp, int left, int right){
	int center;
	if (left < right){
		center = left + (right - left) / 2;
		mSort(A, tmp, left, center);
		mSort(A, tmp, center, right);
		Merge(A,tmp,left,center+1,right);
	}
}
void mergeSort(vector<int> A, int N){
	vector<int> tmp(N);
	mSort(A, tmp, 0, N - 1);
}

五、快速排序

1,思想:从待排序记录中选取一个记录为枢纽元,其关键字为K,然后将其余关键字小于K的记录移到前面,而关键字大于K的记录移到后面,结果将待排序的记录序列分为两个子表,最后将关键字为K的记录插到其分界线的位置处。

      Tips:枢纽元的选择:一般做法是使用左端、右端和中心位置的三个元素的中值作为枢纽元。

2,时间复杂度:  平均 O(nlogn)    最坏 O(n^2).

3,稳定性:不稳定排序。{3,1,2,2}

4,过程分析

  初始         6  1  2  7  9  3  4  5  10  8

第一趟       8  1  2  7  9  3  4  5  10  6    (交换枢纽元和最后元素)

                   5  1  2  4  3  9  7  8  10  6    

第二趟       5  1  2  4  3  6  9  7  8  10    (枢纽元两边继续排序)

                   2  1  5  4  3  6  8  7  10  9

5,伪码

int median3(vector<int> A, int left, int right){  //  找出三个数中值并放在最后
	int center = left + (right - left) / 2;
	if (A[left] > A[center])
		swap(A[left], A[center]);
	if (A[left] > A[right])
		swap(A[left], A[right]);
	if (A[center] > A[right])
		swap(A[center], A[right]);

	swap(A[center], A[right]);
	return A[right];
}
#define Cutoff (3)
void quickSort(vector<int> A,int left,int right){
	int i, j;
	int pivot;
	if (left + Cutoff <= right){
		pivot = median3(A, left, right);
		i = left, j = right;
		while (1){
			while (A[++i] < pivot){}
			while (A[--j] > pivot){}
			if (i < j)
				swap(A[i], A[j]);
			else
				break;
		}
		swap(A[i], A[right]);
		quickSort(A, left, i - 1);
		quickSort(A, i + 1, right);
	}
	else
		insertionSort(A + left, right - left + 1); // 规模小于一定大小时,用插入排序
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值