关于排序算法的总结、

版权声明:吸猫大法、 https://blog.csdn.net/sasuke__/article/details/79839350

具体可以参考(有动图演示很好理解):传送门




1.冒泡排序

冒泡排序还可以用来求逆序数,我们知道冒泡排序每一次的交换原序列逆序数减1,所以我们只需要统计交换了多少次即可得知这个序列的逆序数

冒泡排序可以是稳定的排序也可以是不稳定的排序,看自己的写法

void bubbleSort (int arr[], int n) {
	for (int i = 0; i < n; ++i) {
		for (int j = 1; j < n - i; ++j) {
			if (arr[j - 1] > arr[j]) {
				int tmp = arr[j - 1];
				arr[j - 1] = arr[j];
				arr[j] = tmp;
			}
		}
	}
	for (int i = 0; i < n; ++i) {
		printf("%d ", arr[i]);
	}
	puts("");
}


int main() {
	int arr[] = {3, 2, 1, 5, 7, 9, 6, 8, 4};
	bubbleSort(arr, sizeof(arr) / sizeof(int));
	return 0;
} 


2.选择排序

每次选择当前未排序序列中最小的放到已经排序好的序列的尾端,注意它是不稳定排序

比如 4,4,1,2 很显然我们第一趟排序之后变成 1, 4, 4, 2 原本第一个4到了原本第二个4的后面

void selectionSort (int arr[], int n) {
	for (int i = 0; i < n; ++i) {
		int id = i;
		for (int j = i; j < n; ++j) {
			if (arr[id] > arr[j]) {
				id = j;
			}
		}
		int tmp = arr[id];
		arr[id] = arr[i];
		arr[i] = tmp;
	}
	for (int i = 0; i < n; ++i) {
		printf("%d ", arr[i]);
	}
	puts("");
}

int main() {
	int arr[] = {3, 2, 1, 5, 7, 9, 6, 8, 4};
	selectionSort(arr, sizeof(arr) / sizeof(int));
	return 0;
} 


3.插入排序

数组前部分是已经排序好的,后部分是待排序的,每次排序待排序数组中的第一个,然后和已经排序的数组进行比较,直到插入到合适的位置

其实也类似冒泡排序,也属于稳定排序

void insertSort (int arr[], int n) {
	for (int i = 1; i < n; ++i) {
		int j = i;
		while (j > 0 && arr[j] < arr[j - 1]) {
			int tmp = arr[j];
			arr[j] = arr[j - 1];
			arr[j - 1] = tmp;
			j--;
		}
	}
	for (int i = 0; i < n; ++i) {
		printf("%d ", arr[i]);
	}
	puts("");
}


int main() {
	int arr[] = {3, 2, 1, 5, 7, 9, 6, 8, 4};
	insertSort(arr, sizeof(arr) / sizeof(int));
	return 0;
} 


4.希尔排序

算法思想就是在插入排序的情况下尽量减少向前移动的次数

因为这个涉及到间隔排序,所以这也是不稳定的排序算法

void shellSort (int arr[], int n) {
	int gap = (n >> 1);
	while (gap > 0) {
		for (int i = 0; i < gap; ++i) {
			for (int j = i + gap; j < n; j += gap) {
				for (int k = j; k - gap >= 0; k -= gap) {
					if (arr[k] < arr[k - gap]) {
						int tmp = arr[k];
						arr[k] = arr[k - gap];
						arr[k - gap] = tmp;
					}
				}
			}
		}
		gap >>= 1;
	}
	for (int i = 0; i < n; ++i) {
		printf("%d ", arr[i]);
	}
	puts("");
}


int main() {
	int arr[] = {3, 2, 1, 5, 7, 9, 6, 8, 4};
	shellSort(arr, sizeof(arr) / sizeof(int));
	return 0;
} 


5.快速排序

如果数据是 1 1 1 1 1这样的,快排可以退化到O(n^2)的复杂度

int Sort (int arr[], int l, int r) {
	int i = l, j = r;
	int x = arr[l];
	while (i < j) {
		while (i < j && arr[j] >= x)	--j;
		arr[i] = arr[j];
		while (i < j && arr[i] <= x)	++i;
		arr[j] = arr[i];
	}
	arr[i] = x;
	return i;
}
void quickSort (int arr[], int l, int r) {
	if (l < r) {
		int mid = Sort(arr, l, r);
		quickSort(arr, l, mid);
		quickSort(arr, mid + 1, r);
	}
}


int main() {
	int arr[] = {3, 2, 1, 5, 7, 9, 6, 8, 4};
	quickSort(arr, 0, sizeof(arr) / sizeof(int) - 1);
	for (int i = 0; i < sizeof(arr) / sizeof(int); ++i) {
		printf("%d ", arr[i]);
	}
	puts("");
	return 0;
} 


6.归并排序

稳定不稳定取决你怎么写

void Sort (int arr[], int l, int r, int mid) {
	int i = l, j = mid + 1;
	int tmp[r - l + 5];
	int cnt = 0;
	while (i <= mid && j <= r) {
		if (arr[i] <= arr[j]) {
			tmp[cnt++] = arr[i++];
		} else {
			tmp[cnt++] = arr[j++];
		}
	}
	while (i <= mid) {
		tmp[cnt++] = arr[i++];
	}
	while (j <= r) {
		tmp[cnt++] = arr[j++];
	}
	for (int i = l; i <= r; ++i) {
		arr[i] = tmp[i - l];
	}
}
void mergeSort (int arr[], int l, int r) {
	if (l < r) {
		int mid = (l + r) >> 1;
		mergeSort(arr, l, mid);
		mergeSort(arr, mid + 1, r);
		Sort(arr, l, r, mid);
	}
}


int main() {
	int arr[] = {3, 2, 1, 5, 7, 9, 6, 8, 4};
	mergeSort(arr, 0, sizeof(arr) / sizeof(int) - 1);
	for (int i = 0; i < sizeof(arr) / sizeof(int); ++i) {
		printf("%d ", arr[i]);
	}
	puts("");
	return 0;
} 


7.堆排序

void Sort (int arr[], int start, int end) {
	int dad = start;
	int son = dad * 2 + 1;
	while (son < end) {
		if (son + 1 < end && arr[son] < arr[son + 1]) {
			son++;
		}
		if (arr[dad] >= arr[son]) {
			return ;
		}
		swap(arr[dad], arr[son]);
		dad = son;
		son = dad * 2 + 1;
	}
}
void heapSort (int arr[], int n) {
	for (int i = (n - 1) / 2; i >= 0; --i) {
		Sort(arr, i, n);
	}
	for (int i = n - 1; i > 0; --i) {
		swap(arr[i], arr[0]);
		Sort(arr, 0, i);
	}
	for (int i = 0; i < n; ++i) {
		printf("%d ", arr[i]);
	}
	puts("");
}


int main() {
	int arr[] = {3, 2, 1, 5, 7, 9, 6, 8, 4};
	heapSort(arr, sizeof(arr) / sizeof(int));
	return 0;
} 



还有三种找时间再写、

8.计数排序

时间复杂度O(n + k),k是待排序数组中的最大值,是一种稳定排序,但是需要开辟一段额外辅存

void countingSort (int arr[], int n) {
	int maxn = 0;
	for (int i = 0; i < n; ++i) {
		maxn = max(maxn, arr[i]);
	}
	int basket[maxn + 5];
	mst(basket, 0);
	for (int i = 0; i < n; ++i) {
		basket[arr[i]]++;
	}
	int cnt = n;
	for (int i = maxn; i >= 0; --i) {
		while (basket[i] > 0) {
			basket[i]--;
			arr[--cnt] = i;
		}
	}
	for (int i = 0; i < n; ++i) {
		printf("%d ", arr[i]);
	}
	puts("");
	return ;
}

int main() {
	int arr[] = {3, 2, 1, 5, 7, 9, 6, 8, 4};
	countingSort(arr, sizeof(arr) / sizeof(int));
	return 0;
} 

9.基数排序

时间复杂度O(2 * n * maxDijit),另外开需要开辟n个空间的辅存,属于稳定排序,

void radixSort (int arr[], int n) {
	int maxDigit = 1;
	for (int i = 0; i < n; ++i) {
		int tmp = arr[i];
		int cnt = 0;
		while (tmp > 0) {
			tmp /= 10;
			cnt++;
		}
		maxDigit = max(maxDigit, cnt);
	}
	printf("%d\n", maxDigit);
	int dev = 1;
	int mod = 10;
	vector<int> vt[10];
	for (int i = 0; i < maxDigit; ++i, dev *= 10) {
		for (int j = 0; j < n; ++j) {
			int bucket = (arr[j] / dev) % mod;
			vt[bucket].push_back(arr[j]);
		}
		int pos = 0;
		for (int j = 0; j < 10; ++j) {
			for (int k = 0; k < (int)vt[j].size(); ++k) {
				arr[pos++] = vt[j][k];
			}
			vt[j].clear();
		}
	}
	for (int i = 0; i < n; ++i) {
		printf("%d ", arr[i]);
	}
	puts("");
	return ;
}

int main() {
	int arr[] = {3, 2, 1, 5, 7, 9, 6, 8, 4, 100, 19, 400, 3000, 20};
	radixSort(arr, sizeof(arr) / sizeof(int));
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/sasuke__/article/details/79839350