数据结构中常见排序算法复习

冒泡排序

思想:从前往后遍历,每次把未排序数组中最大的元素交换到数组最后。
代码实现:2个for循环,第一个循环表示冒泡次数,第二个循环从前往后遍历未排序数组,如果前面的元素大于后面的元素,交换,直至到达已排序部分的最前面

void bubbleSort(int a[], int left, int right) {
    
    
	for (int i = 1; i < right-left+1; i++) {
    
    
		for (int j = left; j < right+1-i; j++) {
    
    
			if (a[j] > a[j+1]) {
    
    
				int temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
			}
		}
	}
}

快速排序

快速排序也是通过比较交换元素达到最终数组有序,快速排序比冒泡排序快在其使用了分治的方法。
通常以第一个元素为轴,使用双指针遍历数组,指针 i i i从前向后与轴元素对比,指针 j j j从后向前与轴元素对比。
如果指针 i i i的元素大于轴元素,指针 j j j的元素小于轴元素,交换;最后交换轴元素到指针 i i i和指针 j j j的交汇点。
这样一趟扫描之后,轴元素左边的元素都小于轴元素,右边的元素都大于轴元素,继续分治。

void quickSort(int a[], int left, int right) {
    
    
	if (left >= right) return;
	int i = left, j = right, base = a[left];
	while (i < j) {
    
    
		while (a[j] >= base && i < j) j--;
		while (a[i] <= base && i < j) i++;
		if (i < j) {
    
    
			int temp = a[i];
			a[i] = a[j];
			a[j] = temp;
		}
	}
	a[left] = a[i];
	a[i] = base;
	quickSort(a, left, i-1);
	quickSort(a, i+1, right);
}

选择排序

思想:对于未排序部分 [ i , n ] [i,n] [i,n],选择最小的元素与 a [ i ] a[i] a[i]交换;这样,每次扫描,前面的已排序部分长度加一。

void insertSort(int a[], int left, int right) {
    
    
	for (int i = left+1; i <= right; i++) {
    
    
		int temp = a[i], j = i;
		while (j-1 >= left && temp < a[j-1]) {
    
    
			a[j] = a[j-1];
			j--;
		}
		a[j] = temp;
	}
}

堆排序

什么是堆?完全二叉树,结点的值大于其左右子树的值。
如果结点的值小于左子树或者右子树的值怎么办?把左右子树中较大的值和结点的值交换。交换后还要判断换下来的值是否还是小于其左子树或者右子树,如果是,继续交换。
这一操作即下面的代码中的 s i f t ( ) sift() sift()函数
什么是堆排序呢?因为堆的性质,最大的结点肯定是根节点,把根节点交换到数组最后,这个时候最后的结点到了根节点,堆被破坏了,对未排序数组重新 s i f t ( ) sift() sift(),再把根节点与未排序数组(即堆)的最后结点交换,直至整个数组有序。
另外,堆是二叉树,但是用数组实现正好可以利用完全二叉树的性质:当前结点的下标为 i i i,左孩子结点的下标为 2 ∗ i 2*i 2i,右孩子结点的下标为 2 ∗ i + 1 2*i+1 2i+1

void sift(int a[], int k, int m) {
    
    
	int i = k;
	int left = 2 * i, right = 2 * i + 1;
	while (left <= m) {
    
    
		int t = left;
		right = left+1;
		if (right <= m && a[right] > a[t]) {
    
    
			t = right;
		}
		if (a[i] > a[t]) break;
		int temp = a[i];
		a[i] = a[t];
		a[t] = temp;
		i = t;
		left = 2 * i;
	}
}
void heapSort(int a[], int left, int right) {
    
    
	//初始建堆
	for (int i = (right+left-1)/2; i >= left; i--) {
    
    
		sift(a, i, right);
	}
	for (int i = 0; i < right-left; i++) {
    
    
		//堆顶元素与最后的未排序元素交换
		int temp = a[left];
		a[left] = a[right-i];
		a[right-i] = temp;
		//重新建堆
		sift(a, 1, right-i-1);
	}
}

直接插入排序

思想:将要插入的元素(数组中未排序的元素)从后向前与被插入数组(已有序数组)中的元素比较,如果比当前元素小,数组元素右移;直至找到插入位置。

void insertSort(int a[], int left, int right) {
    
    
	for (int i = left+1; i <= right; i++) {
    
    
		int temp = a[i], j = i;
		while (j-1 >= left && temp < a[j-1]) {
    
    
			a[j] = a[j-1];
			j--;
		}
		a[j] = temp;
	}
}

希尔排序

插入排序的一种,选取一个增量d,数组元素对于增量d进行直接插入排序,增量d不断减小至1;这时整个数组有序。
通常增量d选取数组长度一半,折半减少。

void shellSort(int a[], int left, int right) {
    
    
	for (int d = (right-left)/2; d >= 1; d /= 2) {
    
    
		for (int i = left+d; i <= right; i++) {
    
    
			int temp = a[i], j = i;
			while (j-d >= left && temp < a[j-d]) {
    
    
				a[j] = a[j-d];
				j -= d;
			}
			a[j] = temp;
		}
	}
}

以上排序算法只是简要介绍了实现方法,关于时间复杂度等问题并没有讨论。水平有限,有不当之处欢迎批评指正。

猜你喜欢

转载自blog.csdn.net/qq_41685509/article/details/107307041