数据结构与算法入门

任何高大上的技术都需要踏踏实实的基础:算法+数据结构+编译原理+操作系统

白板编程

To summarize: We have seen that computer programming is an art, because it applies accumulated knowledge to the world, because it requires skill and ingenuity, and especially because it produces objects of beauty.

搜索引擎:搜索算法+排序算法
算法的力量:性能优化

计算机科学有两类根本问题。一类是理论:算法,数据结构,复杂度,机器学习,模式识别,等等等。一类是系统:操作系统,网络系统,分布式系统,存储系统,游戏引擎,等等等等。理论走的是深度,是在追问在给定的计算能力约束下如何把一个问题解决得更快更好。而系统走的是广度,是在追问对于一个现实的需求如何在众多的技术中设计出最多快好省的技术组合。

  • 谷歌搜索,0.67s得到结果,上亿的数据;
  • 苹果siri:语音识别,理解人类语言并智能回应;
  • 推荐算法:机器学习;
  • 动画的渲染,运动效果,图形学
  • 游戏,迷宫的生成,扫雷:洪水填充(Flood fill)算法
  • 无人机,计算机视觉,识别图像信息
    这里写图片描述
    这里写图片描述
  • 线性排序-树形结构-图形结构
  • 数据结构很重要
  • 斐波那契堆,线段树,网络流

这里写图片描述
这里写图片描述

To summarize: We have seen that computer programming is an art, because it applies accumulated knowledge to the world, because it requires skill and ingenuity, and especially because it produces objects of beauty.

选择排序(Selection Sort)
简单,但是对于任何数组,选择排序两层循环必须完全完成。

插入排序(Insertion Sort)

 image

image

image

image

image

对于插入循环来说,,提前终止内层循环是一个很重要的性质 。 对于越有序的数组进行排序,时间复杂度会从O(N^2)向O(N)无限接近

冒泡排序(Bubble Sort)

Bubble Sort (没有插入性能好)

var n = [28,34,54,43];
for(var j = 0 ; j < n.length - 1;j++){
    for(var i = 0;i < n.length- 1 - j;i++){
        if(n[i]>n[i+1]){
            var temp = n[i];
            n[i] = n[i+1];
            n[i+1] = temp;
            }
        }
        console.log(n);
    }

插入排序升级,希尔排序(Shell Sort)n二分之三次方

 

2017-05-14_085225

 

Merge Sort 归并排序(本质:递归)

2017-05-14_085833

把数组分成一半,左边的进行排序(分成一半……),右边的进行排序(分成一半……),

最后,会分到一定的程度,每一部分只有一个元素(本身就是有序的)。

然后归并.

2017-05-14_085935

2017-05-14_090014

2017-05-14_090043

二分法,一层层分级,分为3级,8/2=4/2=2/2=1,log(N)层级,

如果归并过程以O(n)的复杂度来解决的话,那么N log(N)

2017-05-14_090200

解决问题:以O(n)的算法来归并,形成新的有序的数组

2017-05-14_090958

2017-05-14_091121

思路:开辟同样大小的临时空间,不过有利有弊,算法的速度提升了,但是需要的内存空间增加了。(在计算机,时间的效率比空间的效率重要的多)

使用三个索引在内存上追踪

蓝色:表示归并过程中最终需要归并的位置

红1,红2:分别指向两个已经排好序的数组

2017-05-14_091931

比较1和2哪个小,先进入归并数组,1进入,然后蓝箭头位移一位,比较2和4

2017-05-14_092159

2017-05-14_092255

2017-05-14_092336

2017-05-14_092422

k表示ij比较后下一个需要放置的位置(在程序中始终满足变量的定义是程序的基础

l(left) r(right)前闭后闭的空间,

2017-05-14_093354

 

 

快速排序(Quick Sort) 20世纪最伟大的算法之一

 

2017-05-14_164932

以一个元素为基点,然后移动到其大于之前元素的位置上。(核心:Partitions

如果e>v,直接融入v,如果e<v,j+1位置元素和e互换位置,然后j++(橙色块增加),I++(紫块增加)

2017-05-14_165659

当我们遍历完后,再进行l和j互换位置,最终:

2017-05-14_170659

退化至O(n^2)的算法,当两端极端不平衡

这里写图片描述

升级

这里写图片描述

这里写图片描述

堆排序(Heap Sort)

优先队列(Priority Queue)

2017-05-14_200313

比如:操作系统把CPU的执行周期划成时间片(一个时间片只能执行一个任务),每个任务都有一个优先级。所以,需要动态选择优先级最高的任务执行

2017-05-14_201112

优先队列主要操作:入队,出队(取出优先级最高的元素)

2017-05-14_201354

2017-05-14_201500

二叉堆(Binary Heap)

2017-05-14_202039

因为完全二叉树的特性(左边的子节点是父节点的二倍),所以我们可以使用数组来存储二叉堆

2017-05-14_202540

从堆中添加元素(Shift Up)

新添加元素依次和父元素比较,如果比父元素大则交换位置

2017-05-14_204040

2017-05-14_204118

2017-05-14_204206

从堆中取出元素(Shift Down)

image

最后一个元素和取出元素替换,count–

image

最后一个元素依次和左右两个子元素比较(取最大值替换),逐层比较,直到终止

image

Heapify

image

叶子节点的父节点和两个叶子对比,然后最大的成为父节点,向上一层一层的比较

image

QQ截图20170515174227

image

 

Selection Sort(从小到大):

image

1.:在选择范围选择出最小的元素,然后和第一位互换位置

2.:在剩下的位置中找出最小的元素

image

image

image

依此类推

image

只能计算int型

#include <iostream>  
#include <algorithm>  
#include <string>  

using namespace std;  

void selectionSort(int arr[], int n){  

    for(int i = 0 ; i < n ; i ++){  
        // 寻找[i, n)区间里的最小值  
        int minIndex = i;  
        for( int j = i + 1 ; j < n ; j ++ )  
            if( arr[j] < arr[minIndex] )  
                minIndex = j;  
         //交换位置  
         swap( arr[i] , arr[minIndex] );  
    }  

}  

int main() {  
    int a[10] = {10,9,8,7,6,5,4,3,2,1};  
    selectionSort(a,10);  
    for( int i = 0 ; i < 10 ; i ++ )  
    cout<<arr[i]<<" ";  
    cout<<endl;  

    return 0;  
####升级:浮点数,字符串,自定义(利用模板来解决)
#include <iostream>  
#include "Student.h"  

using namespace std;  

template<typename T>  
void selectionSort(T arr[], int n){  

    for(int i = 0 ; i < n ; i ++){  

        int minIndex = i;  
        for( int j = i + 1 ; j < n ; j ++ )  
            if( arr[j] < arr[minIndex] )  
                minIndex = j;  

        swap( arr[i] , arr[minIndex] );  
    }  
}  

int main() {  

    // 测试模板函数,传入整型数组  
    int a[10] = {10,9,8,7,6,5,4,3,2,1};  
    selectionSort( a , 10 );  
    for( int i = 0 ; i < 10 ; i ++ )  
        cout<<a[i]<<" ";  
    cout<<endl;  

    // 测试模板函数,传入浮点数数组  
    float b[4] = {4.4,3.3,2.2,1.1};  
    selectionSort(b,4);  
    for( int i = 0 ; i < 4 ; i ++ )  
        cout<<b[i]<<" ";  
    cout<<endl;  

    // 测试模板函数,传入字符串数组  
    string c[4] = {"D","C","B","A"};  
    selectionSort(c,4);  
    for( int i = 0 ; i < 4 ; i ++ )  
        cout<<c[i]<<" ";  
    cout<<endl;  

    // 测试模板函数,传入自定义结构体Student数组  
    Student d[4] = { {"D",90} , {"C",100} , {"B",95} , {"A",95} };  
    selectionSort(d,4);  
    for( int i = 0 ; i < 4 ; i ++ )  
        cout<<d[i];  
    cout<<endl;  

    return 0;  
}  

运算符进行重载:C++预定义中的运算符的操作对象只局限于基本的内置数据类型,但是对于我们自定义的类型(类)是没有办法操作的。

运算符重载的实质就是函数重载或函数多态。运算符重载是一种形式的C++多态。目的在于让人能够用同名的函数来完成不同的基本操作。

运算符重载为类的成员函数的一般语法形式为: 
函数类型 operator 运算符(形参表) 

  
函数体; 

运算符重载为类的友元函数的一般语法形式为: 
friend 
函数类型 operator 运算符(形参表) 

  
函数体; 

//解决.h文件的多重引用问题,.h文件不对外隐藏  
#ifndef INC_02_SELECTION_SORT_USING_TEMPLATE_STUDENT_H  
#define INC_02_SELECTION_SORT_USING_TEMPLATE_STUDENT_H  

#include <iostream>  
#include <string>  

//容易出现命名空间污染的问题  
using namespace std;  


struct Student{  

    string name;  
    int score;  
    //运算符重载  
    bool operator<(const Student& otherStudent){  
        return score != otherStudent.score ?  
               score > otherStudent.score : name < otherStudent.name;  
    }  

    friend ostream& operator<<(ostream &os, const Student &student){  

        os<<"Student: "<<student.name<<" "<<student.score<<endl;  
        return os;  
    }  
};  

#endif //INC_02_SELECTION_SORT_USING_TEMPLATE_STUDENT_H  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值