主頁 > 前端設計 > 插入排序演算法原理、復雜度及python實作

插入排序演算法原理、復雜度及python實作

2020-09-24 02:53:21 前端設計

目錄

  • 插入排序演算法原理
  • 偽代碼及Python實作
    • 偽代碼
    • python代碼實作
  • 演算法分析(RAM模型)
  • 時間復雜度

插入排序演算法原理

這個演算法要解決的問題是,怎么對序列 A = ( a 1 , a 2 , a 3 , . . . a n ) A=(a_1,a_2,a_3,...a_n) A=(a1?,a2?,a3?,...an?)重新排序,
一種暴力排序的方法是,每一個回圈中,通過兩兩比較,找到現有序列中最小值,依次放到一個新序列中(已經放到新序列中的數,下一個找最小值的回圈就不再參與),這樣,為了排出有序列,需要比較 n ( n ? 1 ) 2 \frac{n(n-1)}{2} 2n(n?1)?次,也就是說,其時間復雜度為 O ( n 2 ) O(n^2) O(n2),相對較高,并且,因為要形成一個新的容器存放排好序的序列,在大資料的情況下,很占記憶體,即該演算法空間復雜度也較高,
如何改進這種暴力解法?首先,要降低空間復雜度,需要減少新容器中的元素;其次,要降低時間復雜度,要減少元素比較的次數,
從空間復雜度上優化該暴力演算法的思路可以類比撲克牌抓牌時候的排序程序,每新抓一張牌,會把這張牌和已有的牌比較大小,依此選擇插入點,因此,每次抓牌之前,手中的牌都是一個排好序的序列,歸結到演算法上,是每次將一個數插入到合適的位置中,
若要將序列從小到大排序,可以將這一程序抽象為:先在序列 A A A抽出第2個元素 a 2 a_2 a2?,將其與 a 1 a_1 a1?比較大小,若 a 2 < a 1 a_2<a_1 a2?<a1?,將 a 2 a_2 a2?放在 a 1 a_1 a1?左側,若 a 2 > a 1 a_2>a_1 a2?>a1?,將 a 2 a_2 a2?放在 a 1 a_1 a1?右側,這樣,在 A A A中排好了兩個元素的有序子列 ( a 1 ′ , a 2 ′ ) (a_1^{'},a_2^{'}) (a1?,a2?)本次排序結束再抽出 a 3 a_3 a3?,將其與 a 2 ′ a_2^{'} a2?比較,若大于,令 a 3 ′ = a 3 a_3^{'}=a_3 a3?=a3?,其他元素均不變,本次排序結束,若小于,先令 a 3 ′ = a 2 ′ a_3^{'}=a_2^{'} a3?=a2?再將 a 3 a_3 a3? a 1 ′ a_1^{'} a1?比較,若大于,令 a 2 ′ = a 3 a_2^{'}=a_3 a2?=a3?本次排序結束,若小于 a 1 ′ a_1^{'} a1?,因為 a 1 ′ a_1^{'} a1?左邊沒有其他數了, a 3 a_3 a3?只能放在 a 1 ′ a_1^{'} a1?左邊,也就是令 a 2 ′ = a 1 ′ a_2^{'}=a_1^{'} a2?=a1? a 1 ′ = a 3 a_1^{'}=a_3 a1?=a3?本次排序結束,由特例可以發現,整個排序程序有兩次回圈,大回圈是從序列A中依此抽元素 a k a_k ak?,小回圈是將 a k a_k ak? A ′ A^{'} A中每個元素比較,小回圈中止條件是 a k > a j ′ a_k>a_j^{'} ak?>aj? a k a_k ak?插到 a j ′ a_j^{'} aj?右側, a j + 1 ′ a_{j+1}^{'} aj+1?左側),或是 j ? 1 = 0 j-1=0 j?1=0 a k a_k ak?插到序列最左側),回圈繼續條件則反過來,
可以算出,該方法時間復雜度仍是 O ( n 2 ) O(n^2) O(n2),但因為該解法使用原地排序,只要建立一個存放待插入元素的容器,空間復雜度會比暴力解法低很多,
據此,可以寫出該程序的代碼,

偽代碼及Python實作

偽代碼


for j=2 to len(A)
//為了避免在賦值的程序中數字丟失,需要另設一個引數存放每次要插入的元素,可以試試如果不設key會怎樣
//這里可看出,相比于暴力解法,該解法大大降低了空間復雜度,暴力解法需要建立一個和原序列一樣長的容器,而該解法只要建立單元素容器,
  key = a[j]
  //默認條件是j之前的數已經排好序,因為代碼正確執行后,這一條件一定成立,這是理解該代碼的難點,
  //每次都是先和序列中前一個數比大小,這里的a[i]相當于A'序列中的數,
  i = j-1
  //小回圈,這里用while書寫,因為回圈次數未知,根據本文第一部分的分析,可寫出回圈繼續條件
  while key < a[i] & i>0
  //新元素小于A'第i個值,則A’第i個值往后移一位,即A'中第i+1個元素被賦值為原第i個元素的值
      a[i+1]=a[i]
      //注意while回圈中要規定回圈方向(for則不需要),否則會停住,此處是往A'的左側走
      i=i-1
      //若新元素大于等于A'第i個值,則將該元素插到A'第i+1個位置,同時回圈結束,新元素右側的元素位置都已經更新過,左側的則不用變,
      //若新元素小于A'所有值,即掃描到了i=0,則回圈結束,該元素插到A’第1個位置,也即i+1,故兩種情況可以統一表示,
  a[i+1]=key
    //一個新元素的插入完成,從原序列中抽下一個元素,

python代碼實作

構造一個實體:對序列A=[1,4,6,3,5,10,7,3,8]從小到大排序,
當然,用python內置的sorted函式可以一次性完成排序:

sorted(A, reverse=FALSE)

如果要自己撰寫一個排序函式,如何實作呢?可以根據上述偽代碼寫出python代碼:

//升序排列
def sort(lista):
    for j in range(1,len(lista)):
        key = lista[j]
        i = j-1
        while key > lista[i]  and i>=0:
            lista[i+1]=lista[i]
            i = i-1
        lista[i+1]=key
        print(lista)
sort(A)

//降序排列只要把key > lista[i]換成key<lista[i]即可

演算法分析(RAM模型)

在RAM模型中,假定:1、陳述句只能是真實的基本計算機指令,而不能是一個封裝好的包,2、每一陳述句的執行時間是一個常量,3、不同陳述句不能并行計算,
雖然這些條件不一定成立,但在分析演算法時間復雜度中有很大作用,
下圖是插入排序演算法每一步的執行時間與執行次數統計(圖源自《演算法導論》),

在這里插入圖片描述

為何第一句運行次數為n而非n-1?需要注意for,while回圈陳述句執行測驗次數比執行回圈體次數多1,
t j t_j tj?指第j個元素進行插入時,進行while回圈測驗的次數(注意比回圈體執行次數多1),回圈體執行次數即待插入元素與A‘序列元素比較的次數,取決于是序列排序程度,最好情況是完全升序,這樣即不用執行回圈體, t j = 1 t_j=1 tj?=1,最壞情況是完全降序,這樣待插入元素需要和j之前的j-1個元素比較,則有 t j = j t_j=j tj?=j,可以總結出技巧:同一級回圈體內的陳述句執行次數應當是相同的,while下面的陳述句實際是和for回圈一級的,因此執行次數也是n-1,
根據RAM的假設,若要知道該演算法耗費總時間,求這些步的時間次數乘積和即可,
計算可得,在最好情況下, T ( n ) = a n + b T(n)=an+b T(n)=an+b
最壞情況下, T ( n ) = a n 2 + b n + c T(n)=an^2+bn+c T(n)=an2+bn+c
這里也可以看出,演算法運行時間取決于很多因素:輸入規模(n)、資料排序程度、單步運行時間……

時間復雜度

由上述部分可以看出,演算法運行時間有最壞情況,也有最好情況,但演算法分析一般只看最壞情況,1、最壞情況確定了演算法運行時間的上界,在演算法時間復雜度的比較上,如果可以證明A演算法的最壞情況都比B演算法的最好情況快,那A在這一層面上一定是優于B演算法的,2、一般來說,平均情況和最壞情況一樣壞,在插入排序中,平均情況是有一半數是升序排好的, t j = j / 2 t_j=j/2 tj?=j/2,這樣算出的T(n)仍然有二次項,
并且,我們更關注的是演算法運行時間的增長率,或者說我們作不同演算法的比較時,統一將n視為無窮大,此時,常數系數也可以被忽略,因此,我們定義時間復雜度 O ( n ) O(n) O(n)為當n趨向無窮大時,其運行時間增長率的決定因素,即T(n)最高項的非常數因子,因此,在暴力排序和插入排序中,都有 O ( n ) = n 2 O(n)=n^2 O(n)=n2
對于最高項階數相同的演算法,比較其復雜度則可以看其最高項系數,如A演算法有 O ( n ) = 2 n O(n)=2n O(n)=2n,B演算法有 O ( n ) = n O(n)=n O(n)=n,B時間復雜度更低,
當然,當輸入規模較小時,常數系數和低階項的影響可能會占上風,但總會存在臨界規模,高于該規模,高階項起決定作用,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/115964.html

標籤:其他

上一篇:爬取糗事百科,我是專業的!

下一篇:我的一點思考-關于計算機專業-關于計算機語言

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more