哈佛大学公开课:计算机科学cs50 学习笔记及代码练习(第8集:冒泡,选择排序,递归)

0. 前言

这门课讲的排序相当清楚,老师用很容易懂的方式讲原理,代码部分在linux下写,用gdb调试,这才是编程的学习方法。记得以前国内本科也学过,但根本没讲清楚。现在研究生又听这门公开课,发现把原理说清楚之后,代码自己很容易就实现了。

另外gdb调试工具也很好用很重要,但国内学的时候老师甚至没有提过。

1. gdb 调试工具的用法

几个命令:run,break, continue, next, step

https://blog.csdn.net/shaozhenghan/article/details/81370240

2. 冒泡排序。

1 到 8  8个整数,从小到大排序。

最坏的情况,初始排列是:8,7,6,5,4,3,2,1

冒泡排序是相邻元素两两比较,然后交换。在最坏情况下需要交换8*8=64次。

因此时间复杂度是O(n^2)

以上是听课的理论,下面是课后自己写代码练习,从小到大排序。

代码实现1--C语言

#include <stdio.h>

void swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

void printArray(const int array[], size_t size)
{
    for(size_t i = 0; i != size; ++i)
    {
        printf("%d\n", *(array+i));
    }
}

// From small to large
void bubbleSort(int array[], size_t size)
{
    for(size_t i = 0; i != size-1; ++i)
        for(size_t i = 0; i != size-1; ++i)
        {
            if(array[i] > array[i+1])
                swap(array+i, array+i+1);
        }
}


int main(int argc, char const *argv[])
{
    int a[8] = {8,7,6,5,4,3,2,1};
    size_t size = 8;
    printArray(a, size);
    bubbleSort(a, size);
    printArray(a, size);
    return 0;
}

需注意C语言没有传引用形参!所以C语言版本的必须用指针来写swap函数。

 

代码实现2--C++

#include <iostream>

void swap(int &a, int &b)
{
    int tmp = a;
    a = b;
    b = tmp;
}

void printArray(const int array[], size_t size)
{
    for(size_t i = 0; i != size; ++i)
    {
        std::cout << array[i] << std::endl;
    }
}

// From small to large
void bubbleSort(int array[], size_t size)
{
    for(size_t i = 0; i != size-1; ++i)
        for(size_t i = 0; i != size-1; ++i)
        {
            if(array[i] > array[i+1])
                swap(array[i], array[i+1]);
        }
}


int main(int argc, char const *argv[])
{
    int a[8] = {8,7,6,5,4,3,2,1};
    size_t size = 8;
    printArray(a, size);
    bubbleSort(a, size);
    printArray(a, size);
    return 0;
}

数组是以指针形式传递给函数的,所以函数一开始并不知道数组的确切尺寸,所以应该提供一些额外的信息。C++中常用方法有两种:1. 显示地传递一个表示数组大小的形参,这也是C语言和C++11标准之前常用的; 2. 在C++11标准中,可以传递指向数组首元素和尾后元素的指针, 用std::begin() 和 std::end()  函数,更简单,更安全,避免下标越界或者访问非法指针造成segmentation error。

我这里只用了第一种,第二种见我这篇博客:https://blog.csdn.net/shaozhenghan/article/details/81437799

 

代码实现3--C++ 容器vector版本

#include <iostream>
#include <vector>

void swap(int &a, int &b)
{
    int tmp = a;
    a = b;
    b = tmp;
}

void printArray(const std::vector<int> &intvec)
{
    for(auto &i : intvec)
    {
        std::cout << i << " ";
    }
    std::cout << "\n";
}

// From small to large
void bubbleSort(std::vector<int> &intvec)
{
    for(size_t i = 0; i != intvec.size()-1; ++i)
        for(auto it = intvec.begin(); it != intvec.end()-1; ++it)
        {
            if((*it) > *(it+1))
                swap(*it, *(it+1));
        }
    // printArray(intvec);
}


int main(int argc, char const *argv[])
{
    std::vector<int> a = {8,7,6,5,4,3,2,1};
    std::cout << "before sorting" << std::endl;
    printArray(a);
    bubbleSort(a);
    std::cout << "after sorting" << std::endl;
    printArray(a);
    return 0;
}

使用c++的vector容器类型,可以使用迭代器,范围for循环,auto类型等C++11新标准特性,使得代码更安全,不容易出现下标越界缓冲区溢出等严重错误。

需注意,当vector类型做形参时,如果不用引用会发生拷贝构造!所以bubbleSort函数要这样写:void bubbleSort(std::vector<int> &intvec); 不用引用就起不到排序改变vector对象的效果。这一点与数组不同,数组做形参时只能传递数组指针,不会发生拷贝构造,函数内部对数组的改变能起到改变实参的效果。

另外printArray函数形参要写成常量引用,因为函数内部不会改变vector对象,这一点要养成习惯。

 

3. 选择排序

1 到 8  8个整数,从小到大排序。

假设初始排列是:4,2,6,8,1,3,7,5

那么经过第一次排序后,变为:1,2,6,8,4,3,7,5, 即4和1互换了。

第二次从第二项开始比较,因为2是从第二项开始最小的数,所以不变。

最坏情况下(初始排列为:8,7,6,5,4,3,2,1),需要交换8+7+6+……+1 次,即n+……+1=n(n+1)/2

时间复杂度是O(n^2). (只考虑高次项)

代码实现一下:

#include <iostream>

void swap(int &a, int &b)
{
    int tmp = a;
    a = b;
    b = tmp;
}

void printArray(const int array[], size_t size)
{
    for(size_t i = 0; i != size; ++i)
    {
        std::cout << array[i] << " ";
    }
    std::cout << "\n";
}

// From small to large
void selectSort(int array[], size_t size)
{
    for(size_t j = 0; j != size-1; ++j)
        for(size_t i = j+1; i != size; ++i)
        {
            if(array[j] > array[i])
                swap(array[j], array[i]);
        }
}


int main(int argc, char const *argv[])
{
    int a[8] = {4, 2, 6, 8, 1, 3, 7, 5};
    size_t size = 8;
    printArray(a, size);
    selectSort(a, size);
    printArray(a, size);
    return 0;
}

 

4. 递归调用

好处:代码简洁,避免了循环。

坏处:有内存溢出的风险。segmentation error 段错误(核心已转储)

 

例子:求1到整数m的累加和

int sum_one_to_m (int m)
{
    if (m <= 0)
        return (0);
    else
        return (m + sum_one_to_m (m-1));
}

 

哈佛大学公开课程讲义 哈佛大学 哈佛公开课:公平与正义(中英字幕) http://www.manfen.net/thread-6680-1-1.html 哈佛大学最受欢迎的开放课程:哈佛幸福课 http://www.manfen.net/thread-6801-1-1.html 哈佛大学公开课——好市民自由与适应 http://www.manfen.net/thread-6650-1-1.html 哈佛大学公开课——自由选择我属于谁? http://www.manfen.net/thread-6649-1-1.html 耶鲁大学 耶鲁大学开放课程—哲学:死亡 http://www.manfen.net/thread-6303-1-1.html 耶鲁大学开放课程:聆听音乐(共23讲) http://www.manfen.net/thread-6298-1-1.html 耶鲁大学开放课程:古希腊历史简介 中英双语字幕 http://www.manfen.net/thread-7323-1-1.html 耶鲁大学开放课程:有关食物的心理学,生物学和政治学 http://www.manfen.net/thread-7275-1-1.html 耶鲁课程.:欧洲文明 http://www.manfen.net/thread-7074-1-1.html 耶鲁大学开放课-金融市场 http://www.manfen.net/thread-6923-1-1.html 耶鲁大学开放课程:基础物理 http://www.manfen.net/thread-6734-1-1.html 耶鲁大学公开课:1945年后的美国小说 http://www.manfen.net/thread-6837-1-1.html 耶鲁大学开放课程:美国内战与重建 http://www.manfen.net/thread-6804-1-1.html 耶鲁大学开放课程:罗马建筑 http://www.manfen.net/thread-6803-1-1.html 耶鲁大学开放课程:古希腊历史简介(中英双语字幕) http://www.manfen.net/thread-6788-1-1.html 耶鲁大学开放课程:旧约全书导论 http://www.manfen.net/thread-6789-1-1.html 耶鲁大学开放课程:生物医学工程探索 http://www.manfen.net/thread-6733-1-1.html 耶鲁大学开放课程:【欧洲文明】 http://www.manfen.net/thread-6732-1-1.html 耶鲁大学开放课程:心理学导论 http://www.manfen.net/thread-6284-1-1.html 耶鲁大学开放课程:博弈论 http://www.manfen.net/thread-6291-1-1.html 耶鲁大学开放课程-社会学:全球人口增长问题 http://www.manfen.net/thread-9142-1-1.html 耶鲁大学开放课程-人文学科:现代诗歌 http://www.manfen.net/thread-9144-1-1.html 耶鲁大学开放课程:弥尔顿(共24讲) http://www.manfen.net/thread-9195-1-1.html 耶鲁大学开放课:天体物理学之探索和争议(12讲) http://www.manfen.net/thread-9201-1-1.html 耶鲁大学公开课:解读但丁(24讲) http://manfen.net/thread-10650-1-1.html 耶鲁大学公开课:新生有机化学--32讲 http://www.manfen.net/thread-10689-1-1.html 斯坦福大学 斯坦福大学开放课程 : 傅立叶变换及应用 http://www.manfen.net/thread-6834-1-1.html 斯坦福大学开放课程: 抽象编程 http://www.manfen.net/thread-6822-1-1.html 斯坦福大学公开课:7个颠覆你思想的演讲 http://www.manfen.net/thread-7883-1-1.html 斯坦福大学开放课程-工程学科:机器人学 http://www.manfen.net/thread-9146-1-1.html 斯坦福大学开放课程-编程方法论 http://www.manfen.net/thread-9148-1-1.html 斯坦福大学开放课程:量子力学 http://www.manfen.net/thread-7954-1-1.html 斯坦福大学公开课:商业领袖和企业家 http://www.manfen.net/thread-8051-1-1.html 麻省理工大学 MIT linear algebra http://www.manfen.net/thread-7072-1-1.html MIT physics classes http://www.manfen.net/thread-7065-1-1.html MIT OpenCourseWare -- Calculus http://www.manfen.net/thread-7052-1-1.html Applied Functional Analysis(应用泛函分析) http://www.manfen.net/thread-7051-1-1.html 美国麻省理工大学(MIT)--大学物理本科教学录像. http://www.manfen.net/thread-7047-1-1.html 麻省理工大学开放课:建筑设计(共12讲) http://www.manfen.net/thread-9198-1-1.html 麻省理工大学开放课:经典力学(35讲) http://www.manfen.net/thread-9200-1-1.html 麻省理工大学公开课:音乐的各种声音 http://www.manfen.net/thread-10683-1-1.html 普林斯顿大学 普林斯顿大学公开课:国际座谈会 http://www.manfen.net/thread-7945-1-1.html 普林斯顿大学开放课程:领导能力简介 http://www.manfen.net/thread-7952-1-1.html 普林斯顿大学开放课程:自由意志定理 http://www.manfen.net/thread-7953-1-1.html 普林斯顿大学开放课程:人性 http://www.manfen.net/thread-7884-1-1.html 加大及其分校 美国加州艺术学院讲座设计和工艺 Paul.Discoe.Lecture http://www.manfen.net/thread-7223-1-1.html 美国加州艺术学院讲座:设计和工艺 Jennifer.Broutin.and.Carmen.Trud http://www.manfen.net/thread-7222-1-1.html 美国加州艺术学院讲座:时尚设计 http://www.manfen.net/thread-7221-1-1.html 加大伯克利分校开放课程-操作系统和编程 http://www.manfen.net/thread-9150-1-1.html 加大洛杉矶分校-家庭与夫妇心理学:亲密的关系 http://www.manfen.net/thread-9141-1-1.html 加州伯克利大学公开课:数据统计分析--42 http://manfen.net/thread-10656-1-1.html 加州伯克利大学公开课:社会认知心理学--25 http://www.manfen.net/thread-10672-1-1.html 加州伯克利大学公开课:世界各地人民和国家--共19 http://www.manfen.net/thread-10671-1-1.html 加州伯克利大学公开课:大灾难时期的伦理和公共健康--共14 http://www.manfen.net/thread-10669-1-1.html 加州伯克利大学公开课:综合生物学--39 http://www.manfen.net/thread-10679-1-1.html 牛津大学 牛津大学公开课:《尼采的心灵与自然》 http://manfen.net/thread-10652-1-1.html 牛津大学公开课:《哲学概论》--17 http://manfen.net/thread-10653-1-1.html 剑桥大学 剑桥大学公开课:《人类学》--15 http://www.manfen.net/thread-10684-1-1.html 其它学校 美国名校人文社科lecture http://www.manfen.net/thread-7097-1-1.html 更多公开课请访问:http://www.manfen.net/topic-public-class.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值