关于算法空间复杂度的问题

‘算法空间复杂度’,别以为这个东西多么高大上,我保证你看完这篇文章就能明白。

最近在啃算法,发现非常有趣。在我学习的过程中发现了一个问题,那就是空间复杂度的问题,它绝对是效率的杀手。

关于空间复杂度的介绍(摘自百度)

空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。比如直接插入排序时间复杂度是O(n^2),空间复杂度是O(1) 。而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归都要存储返回信息。一个算法的优劣主要从算法的执行时间和所需要占用的存储空间两个方面衡量。

拿插入排序来说。插入排序和我们现实中打扑克牌时理清牌的那一步很像。拿斗地主来说,我们经常会把顺子理出来,回想下我们是怎么理的?比如我们有这么5张牌9、8、10、7、6。过程应该是这样的:

9、8、10、7、6

从8开始,8发现9比它大,然后8插到9前面。

8、9、10、7、6

然后到10,10发现它比前面2个都大,所以不用动。

8、9、10、7、6

然后到7,7发现10比它大,然后跟10换位置。

8、9、7、10、6

然后7又发现9也比它大,于是又跟9换位置

8、7、9、10、6

然后7又发现8也比它大,于是又跟8换位置

7、8、9、10、6

等等,好像有点不对。到牌‘7’的那一步好像太麻烦了,我们平时是把7拿起来,直接插到8前面就完事了。简单快捷,绝对比一个个插要快。没错!这就是空间复杂度的问题。下面直接上2组代码来校验一下。

   public static void InsertSort(List<int> list)
        {
            for (int i = 0; i < list.Count; i++)
            {
                for (int j = i; j - 1 >= 0; j--)
                {
                    if (list[j - 1] > list[j])
                    {
                        int temp = list[j - 1];
                        list[j - 1] = list[j];
                        list[j] = temp;
                        Console.WriteLine(string.Join(",", list));
                    }
                    else
                        break;

                }
            }
        }

        static void Main(string[] args)
        {
            List<int> list = new List<int>()
            {
                9,8,10,7,6
            };
            InsertSort(list);
            Console.ReadKey();
        }

我们可以看到,这种方法真是很笨。。就是一个一个往前插。。这当然不是我们想要的。。我们再改进下

  public static void InsertSort2(List<int> list)
        {
            for (int i = 0; i < list.Count; i++)
            {
                int j = i;
                int baseNumber = list[j];//先把牌抽出来
                for (; j - 1 >= 0; j--)
                {
                    if (list[j - 1] > baseNumber)
                    {
                        list[j] = list[j - 1];//后面的往前推
                    }
                    else
                        break;
                }
                list[j] = baseNumber;//结束后把牌插入到空位
            }
        }

        static void Main(string[] args)
        {
            List<int> list = new List<int>()
            {
                9,8,10,7,6
            };
            InsertSort2(list);
        }

其实思路就是先抽出1张牌(比如抽出的那张牌的位置为3,注意:现在3是空出来的),如果前一张牌(位置2)比它大,就把2移到3上面去。2就空出来了。

接着再前面那张(位置1)如果比抽出来的牌大,继续往前移。因为2空出来了,1移到2上。现在1空出来了。

然后把抽出来的牌放到1上,完成。

过程如下

8、9、10、7、6

7

8、9、10、  、6

8、9、   、10、6

8、  、9 、10、6

、8、9 、10、6

7、8、9 、10、6

再来看看执行效率方面到底差了多远

 public static void InsertSort(List<int> list)
        {
            for (int i = 0; i < list.Count; i++)
            {
                for (int j = i; j - 1 >= 0; j--)
                {
                    if (list[j - 1] > list[j])
                    {
                        int temp = list[j - 1];
                        list[j - 1] = list[j];
                        list[j] = temp;
                    }
                    else
                        break;
                }
            }
        }

        public static void InsertSort2(List<int> list)
        {
            for (int i = 0; i < list.Count; i++)
            {
                int j = i;
                int baseNumber = list[j];//先把牌抽出来
                for (; j - 1 >= 0; j--)
                {
                    if (list[j - 1] > baseNumber)
                    {
                        list[j] = list[j - 1];//后面的往前推
                    }
                    else
                        break;
                }
                list[j] = baseNumber;//结束后把牌插入到空位
            }
        }

        static void Main(string[] args)
        {
            List<int> list = new List<int>();
            Random random = new Random();
            for (int i = 0; i < 50000; i++)
            {
                list.Add(random.Next());
            }
            Stopwatch watch = new Stopwatch();
            watch.Start();
            InsertSort(list);
            watch.Stop();
            Console.WriteLine(watch.ElapsedMilliseconds);

            watch.Reset();
            watch.Start();
            InsertSort2(list);
            watch.Stop();
            Console.WriteLine(watch.ElapsedMilliseconds);

            Console.ReadKey();
        }

运行结果

是不是吓了一大跳。。竟然差了1234X倍。。算了,我数学不好。

堆排,快排时很多时候都会运用到这种思想。不知道大家有没得到一些帮助呢?平时编程的时候是否也要注意到呢?

时间: 2024-11-09 20:08:21

关于算法空间复杂度的问题的相关文章

算法空间复杂度

‘算法空间复杂度’,别以为这个东西多么高大上,我保证你看完这篇文章就能明白. 最近在啃算法,发现非常有趣.在我学习的过程中发现了一个问题,那就是空间复杂度的问题,它绝对是效率的杀手. 关于空间复杂度的介绍(摘自百度) 空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n)).比如直接插入排序的时间复杂度是O(n^2),空间复杂度是O(1) .而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归都要存储返回信息.一个算法的

转:算法的空间复杂度

转自:算法的空间复杂度 类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数.渐近空间复杂度也常常简称为空间复杂度. 空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度.一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面. 我们在写代码时,完全可以用空间来换取

算法之时间复杂度和空间复杂度

时间复杂度: 定义:在进行算法分析时,语句的总执行次数T(n)是关于问题的规模n的函数,进而分析T(n)随着n的变化情况并确定T(n)的数量级.算法的时间复杂度,也就是算法的时间时间量度,记做:T(n)=O(f(n)).它表示随着问题的规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称时间复杂度.其中f(n)是问题规模n的某个函数. 这样用大写 O()来体现算法时间复杂度的记法,我们称之为大 0 记法 .一般情况下,随着 n 的增大, T(n)增长最慢的算法

算法的时间和空间复杂度

算法(Algorithm)是指用来操作数据.解决程序问题的一组方法.对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别. 那么我们应该如何去衡量不同算法之间的优劣呢? 主要还是从算法所占用的「时间」和「空间」两个维度去考量. 时间维度:是指执行当前算法所消耗的时间,我们通常用「时间复杂度」来描述. 空间维度:是指执行当前算法需要占用多少内存空间,我们通常用「空间复杂度」来描述. 因此,评价一个算法的效率主要是看它的时间复杂度和空间复杂度情况.然

算法(1)--时间和空间复杂度

算法(1)--时间和空间复杂度 初识 算法定义 算法是独立存在的一种解决问题的方法和思想: 求解一个问题步骤的描述 是求解问题的方法 它是指令的有限序列 其中每条指令表示一个或者多个操作 对于算法而言,实现的语言并不重要,重要的是思想 算法特性 确定性:无二义 有穷性:合适时间内可以执行 输入项 输出项 可行性:算法的每一步都是可行的 复杂度 时间复杂度 定义 ? 一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示(语句频度),若有某个辅助函数f(n),使得当n趋近于

第二篇 算法概述及复杂度

虽然本系列随笔是记录数据结构相关的内容,但是我们都知晓算法和数据结构是密不可分的.我们也可以时常看到一个公式“程序设计=数据结构+算法”.数据结构是研究数据之前的关系,以及数据在计算机中的存储形式,而算法是让数据通过一定的形式得到我们需要的结果.这其中包含各种的逻辑运算等. 提及算法,我们会自然的联想到一个关于数学牛人的故事:“高斯7岁那年开始上学.10岁的时候,一天,老师布置了一道题,1+2+3······这样从1一直加到100等于多少.高斯很快就算出了答案,起初高斯的老师布特纳并不相信高斯算

内部排序算法(一):交换排序(冒泡排序,快速排序)

这是我的博文系列<内部排序算法>的第一篇.所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来.所谓内部排序,是指在排序过程中,若整个文件都是放在内存中处理,排序时不涉及数据的内.外存交换(外排序的定义则相反). 内部排序法按照策略可以划分为五类:插入排序.选择排序.交换排序.归并排序和分配排序.待排文件的存储方式采用顺序表(或直接用向量)作为存储结构(其他的存储结构还有以链表作为存储结构等). 在这个系列的博文中,我按照排序算法的给出,排序算法的分析(包括算法的时空复杂度

01.数据结构概念与算法基础

数据结构概念与算法基础 一.数据结构概念 1.数据:是描述客观事务的符号,是计算机中可以操作的对象,是能被计算机识别,并输入给计算机处理的符号集合.数据不仅仅包括整型.实型等数值类型,还包括字符及声音.图像.视频等非数值类型. 2.数据元素:是组成数据的.有一定意义的基本单位,在计算机中通常作为整体处理,也被成为记录.比如畜类中,牛.马.羊都属于数据元素. 3.数据项:一个数据元素可以由若干个数据项组成,数据项是数据不可分割的最小单位.比如人这样的数据元素,可以有眼.耳.鼻等数据项. 4.数据对

[数据结构和算法]算法基本概念

算法基本概念: 算法:用来对数据的操作作描述,是对问题求解的步骤的描述.是一系列将输入转为输出的计算步骤 算法复杂度:分为时间复杂度和空间复杂度时间复杂度:算法中所有语句的频度之和用T(n)表示,记为T(n) = O(n) 常见时间复杂度递增次序:常数 O(1) , 对数阶O(log2^n) , 线性阶O(n) , 线形对数阶O(nlog2^n),平方阶O(n^2),立方阶O(n^3),指数阶O(2^n),O(n!),O(n^n)当n值增大,算法时间复杂度即变大,执行效率变低 最坏时间复杂度:最