@数据结构复习笔记(一):
数据结构的五种排序
这是我的第一天的学习日记——今天主要学的是排序,这里我们就简单的讲一下几种常见的排序:
1.插入排序
2.桶排序
3.冒泡排序
4.选择排序
5.快速排序
先来看排序的输入输出:
给定一个任意无序定长数组num[10]={1,3,5,7,9,2,4,6,8,10}
通过代码处理后数组将变成:{1,2,3,4,5,6,7,8,9,10}
看似简单的过程:可以有很多种处理的方法:
先看看第一种排序:
插入排序:
这种排序算法的思路就是 将下一个需要排的元素插入到之前已排好的数组中去
例如:
{1,3.2,4}
{1}{3,2,4}
{1,3}{2,4}
{1,2,3}{4}
{1,2,3,4}
结束排序
为了提高效率会附设一个监视哨num[0],监视哨有两个作用1.备份待插入的记录,2.防止越界
插入排序的代码:
void InsertSort(int num[], int len) {
int j,k;
for (int i = 1; i < len; i++)
{
k = num[i];
j = i - 1;
while (k<num[j])
{
num[j + 1] = num[j];
j--;
}
num[j + 1] = k;
}
print(num, len);
};
不难发现插入排序难点在于寻找插入的位置,其实也就不难发现这是一个可以在查找上进行优化的一个算法。
对于查找算法的优化,我们不难想到折半查找法,也就衍生了折半插入排序,这里代码不做展示了。(自己懒,没写)
桶排序:
桶排序在某种意义上来说,是效率较高的排序算法,时间复杂度近似O(n).
这里先分析算法的方法:此算法需要知道范围,将范围转化为桶个数,遍历一遍数组,每碰到一个数,就把它扔进相应的桶中(socket[num]++),然后按照每个桶里的数的个数放入原数组。此时排序完成。
当然也可以从空间上优化桶排序
(此处指桶排序中,范围的个数为桶数的十倍或百倍(整数倍)然后在桶外进行桶排序,桶内进行快速排序)
分析一下时间复杂度:
为啥说是近似O(n):
假设有n个数,范围为m(即有m个桶)
初始化桶:m
数组放入桶中:n
桶内排序:(一般采用快速排序)nlog(n/m) //n个桶,每个桶内个数为n/m
最后放回数组:n
实际上的复杂度为:O(2n+m+nlog(n/m))
去掉系数:O(n+m+n(log n - log m))
假设桶的个数等于数的个数(即保证一数一桶)
此时,时间复杂度为O(m+n),近似O(n)
上代码
void SocketSort(int num[], int len) {
int socket[11];//桶排序一般需要知道排序数的范围,以确定桶的个数
memset(socket, 0, sizeof(socket));//初始化桶内计数器
for (int i = 0; i < len; i++)
{
socket[num[i]]++;
}
for (int i = 11; i >0; i--)
{
while (socket[i]>0)
{
cout << i << "\t";
socket[i]--;
}
}
cout << endl;
}
冒泡排序:
最简单的排序:
每一轮排序都选出剩下数中最大的,将其放在最后,选择的方法是:每相邻的两个数进行比较,大的就放在后面,这样每次进行到最后,交换到最后的数一定是该轮最大的
例如
{1,3.2,4}
此处对1,3先进行比较发现3大,把3放在后面,然后对3,2进行比较,发现3大,交换两数的位置即
{1,2,3,4}
还需要进行比较,后面的比较就不做演示了
上代码
void BubbleSort(int num[], int len) {
int t;
for (int i = 0; i < len-1; i++)
{
for (int j = 0; j < len-i-1; j++)
{
if (num[j] > num[j + 1]) {
t = num[j];
num[j] = num[j + 1];
num[j + 1] = t;
}
}
}
print(num, len);
}
选择排序:
选择排序的思路:进行多轮选择,每轮将通过比较最大的数选出来,先标记下来,在此轮最后,标记的数即为本轮最大,放在最后
此方法时间复杂度和冒泡一样都为O(n^2)
例如
{1,3,2,4}
第一轮max先等于1,进行本轮比较,遇到3时,3大,所以现在max=3,最后遇到4,发现4大,max=4
现在把max放在数组尾部,完成第一轮。
此时:{1,3,2,4}
第二轮
max还是先等于1,进行本轮比较之后,max最后等于3此时将末尾与3交换位置
此时{1,2,3,4}
后面还需比较,此处不做讲解
上代码
void SelectSort(int num[], int len) {
int max, temp;//用一个max变量标记每次找到的最大值的序号
for (int i = 0; i < len; i++) {
max = i;//假设第一个数就是最大的,开始用第一个数和每一个比较找到这个最小值;
for (int j = i+1; j < len; j++)
{
if (num[j] > num[max]) {
max = j; //存在比他大的就就把这个下表给max
}
}
if (max != i) { //如果找到了另外一个最大值,max不会等于i,此时将这个max的值与i交换
temp = num[max];
num[max] = num[i];
num[i] = temp;
}
}
print(num, len);
};
快速排序:
目前来说,比较热门的排序,基于快速排序,能解决很多问题,比如比较出名的荷兰国旗问题,就是一趟快速排序解决的。还有bfprt算法也是基于快速排序的(分组快排+特殊基准值)。
现在来看看快速排序的思路:每一趟快速排序,将会选取一个基准数,然后遍历数组,此处遍历数组需要三个指向值。
start:标记数组的头
end:标记数组的尾部
current:可以不需要,为了方便理解,这里加个current变量,即记录当前遍历的值
每一趟快排的思想就是将current的值与基准值进行比较,比基准值大将放在基准值的右边,比基准值小就放在左边
放置数就需要start标记和end标记,用current与start或end交换,交换完之后start,end往中间靠
然后对一趟快排之后的数组,按基准值分割开,分别递归
例如{2,4,1,3,5}
选取2为基准
一趟快排结束:{1,2,5,3,4}
然后对左右递归
最后交换到最后{1,2,3,4,5}
上代码:
void QuickSort(int* num, int start,int end) {
if (start >= end) {
return;
}
int i, j, base, temp;
i = start;
j = end;
base = num[start];
while (i<j)
{
while(num[j] >= base && i < j)
j--;
while (num[i] <= base && i < j)
i++;
if (i < j) {
temp = num[i];
num[i] = num[j];
num[j] = temp;
}
}
num[start] = num[i];
num[i] = base;
QuickSort(num, start, i - 1);
QuickSort(num, i+1, end);
};
放个完整的代码:
// DataStructureTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
/*
详解排序算法:
测试数据:{0,2,4,6,8,1,3,5,7,9}
输出: {0,1,2,3,4,5,6,7,8,9}
*/
//
#include <iostream>
using namespace std;
void print(int num[],int len);
void InsertSort(int num[], int len);
void SocketSort(int num[], int len);
void BubbleSort(int arr[], int n);
void QuickSort(int* num, int start, int end);
void SelectSort(int num[], int len);
int main()
{
//int num[10] = {0,2,4,6,8,1,3,5,7,9};
//print(num, 10);
//BubbleSort(num, 10);
//InsertSort(num,10);
//SocketSort(num,10);
//SelectSort(num,10);
int num1[10] = { 10,2,4,6,8,1,3,5,7,9 };
print(num1, 10);
QuickSort(num1, 0, 9);
print(num1, 10);
}
void InsertSort(int num[], int len) {
int j,k;
for (int i = 1; i < len; i++)
{
k = num[i];
j = i - 1;
while (k<num[j])
{
num[j + 1] = num[j];
j--;
}
num[j + 1] = k;
}
print(num, len);
};
void print(int num[], int len) {
for (int i = 0; i < len; i++) {
cout << num[i] << "\t";
}
cout << endl;
};
void SocketSort(int num[], int len) {
int socket[11];//桶排序一般需要知道排序数的范围,以确定桶的个数
memset(socket, 0, sizeof(socket));//初始化桶内计数器
for (int i = 0; i < len; i++)
{
socket[num[i]]++;
}
for (int i = 11; i >0; i--)
{
while (socket[i]>0)
{
cout << i << "\t";
socket[i]--;
}
}
cout << endl;
}
void BubbleSort(int num[], int len) {
int t;
for (int i = 0; i < len-1; i++)
{
for (int j = 0; j < len-i-1; j++)
{
if (num[j] > num[j + 1]) {
t = num[j];
num[j] = num[j + 1];
num[j + 1] = t;
}
}
}
print(num, len);
}
void SelectSort(int num[], int len) {
int max, temp;//用一个max变量标记每次找到的最大值的序号
for (int i = 0; i < len; i++) {
max = i;//假设第一个数就是最大的,开始用第一个数和每一个比较找到这个最小值;
for (int j = i+1; j < len; j++)
{
if (num[j] > num[max]) {
max = j; //存在比他大的就就把这个下表给max
}
}
if (max != i) { //如果找到了另外一个最大值,max不会等于i,此时将这个max的值与i交换
temp = num[max];
num[max] = num[i];
num[i] = temp;
}
}
print(num, len);
};
void QuickSort(int* num, int start,int end) {
if (start >= end) {
return;
}
int i, j, base, temp;
i = start;
j = end;
base = num[start];
while (i<j)
{
while(num[j] >= base && i < j)
j--;
while (num[i] <= base && i < j)
i++;
if (i < j) {
temp = num[i];
num[i] = num[j];
num[j] = temp;
}
}
num[start] = num[i];
num[i] = base;
QuickSort(num, start, i - 1);
QuickSort(num, i+1, end);
};
今天的分享到此结束啦,欢迎大家讨论!!!!!!