数据结构复习笔记(一):排序

@数据结构复习笔记(一):

数据结构的五种排序

这是我的第一天的学习日记——今天主要学的是排序,这里我们就简单的讲一下几种常见的排序:

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);
};

今天的分享到此结束啦,欢迎大家讨论!!!!!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值