插入排序優化——超越歸并排序的超級算法

插入排序及優化

  • 插入排序算法
    • 算法講解
    • 數據模擬
    • 代碼
  • 優化思路
    • 一、二分查找
    • 二、copy函數
  • 優化后代碼
  • 算法的用途
    • 題目:數星星(POJ2352 star)
      • 輸入輸出格式
        • 輸入格式:
        • 輸出格式
      • 輸入輸出樣例
        • 輸入樣例
        • 輸出樣例
    • 題目講解
      • 步驟如下
      • AC 代碼

在這里插入圖片描述

插入排序算法

在了解如何改進插入排序之前,我們先要了解插入排序的基本算法:

算法講解

插入排序對于少量元素的排序,是一個有效的算法 。

插入排序是一種簡單的排序方法,它是將一個數據插入到已經排好序的有序數組,從而形成一個新的有序數組。

插入排序的工作方式像許多人排序撲克牌:

我們每次從桌子上拿走一張牌并將其插入到手中正確的位置。

為了找到它的正確位置,我們從右到左將它與手中的每張牌進行比較。

因此,手上的牌總是有序。

數據模擬

原本要排序的數為 5 3 4 2 9 1,從小到大排序。


3 5 4 2 9 1        // 將3放到合適的位置(5前面)3 4 5 2 9 1        // 將4放到合適的位置(3、5中間)2 3 4 5 9 1        // 將2放到合適的位置(最前面)2 3 4 5 9 1        // 將9放到合適的位置(最后面)1 2 3 4 5 9        // 將1放到合適的位置(最前面)

排序結束!!!

代碼

#include <iostream>
using namespace std;
int n,a[2000];        //定義數據個數n,排序數組a
int main()
{cin >>n;        //輸入個數for (int i=1;i<=n;i++)cin >>a[i];            //輸入數據for (int i=2;i<=n;i++)    //第一個數本身只有一個元素,所有有序,因此不用參與排序{int j,k=a[i];        //記錄下當前元素for (j=i-1;j>0;j--){if (a[j]>k)        //若前面一個數大于當前元素a[j+1]=a[j];    //則將前面一個元素往后移動elsebreak;        //否則:說明當前元素已經找到了合適的位置,推出循環}a[j+1]=k;        //將當前元素放入數組的合適的位置/*                        輸出排序的過程for (int j=1;j<=n;j++)cout <<a[j] <<" ";cout <<endl;*/}for (int i=1;i<=n;i++)cout <<a[i] <<" ";        //輸出排序好的數組return 0;
}

優化思路

我們發現,插入排序的過程浪費在了查找合適的位置上,那么怎么優化呢?

我們知道,插入排序一直在維護 前 i i i個數是有序的,那么如何快速在有序的數列中查找一個小于(或大于)自己的數呢?

一、二分查找

二分!!!!

那么這樣我們就講查找的時間從 O ( n ) O(n) O(n)縮短為 O ( n l o g ( n ) ) O(n~log(n)) O(n?log(n))!!

忍不住激動!!

可是找到位置不夠,還要進行移動啊。移動的時間復雜度是 O ( n ) O(n) O(n)那么這樣非但沒有優化,反而還增加了查找的時間。。。

希望瞬間破滅!!

但是我會向它屈服嗎???

嗎?

明顯不會!

二、copy函數

我們可以使用一個 S T L STL STL庫里面的一個函數:

copy(a,a+n,a+1);

c o p y copy copy函數!!

這個函數可以在 O ( 1 ) O(1) O(1)的時間范圍內將數組的某一段移動到,
使用方法:
以上面的操作為例子,這表明:

  • a a a數組的第 0 0 0位為開頭
  • a a a數組的第 n ? 1 n-1 n?1位位結尾
  • 將它移動到開頭位第 1 1 1位的位置

那么,這就好辦了,只需要要講兩個結合起來,一個速度與歸并排序相當,代碼比歸并排序簡短許多的超級優化插入排序代碼誕生了:

優化后代碼

#include <bits/stdc++.h>
#define N 2000000
using namespace std;
int n,x,y,f,t[N],k[N];
int main() {scanf("%d",&n);for (int i=1; i<=n; i++) {scanf("%d",&x);f=upper_bound(t+1,t+i,x)-t;		//記錄二分的位置copy(t+f,t+i,t+f+1);	//copyt[f]=x;		//存入數組}for (int i=1; i<=n; i++) {printf("%d ",t[i]);}return 0;
}

輸入數據:

5
4 9 1021 54 3

輸出數據:

3 4 9 54 1021

也是對了好吧~~

算法的用途

這個算法可以快速的在有序數列里面進行操作,也是異常的方便快捷,代碼超級簡短!!
下面給一道可以用這個算法解決的問題:

題目:數星星(POJ2352 star)

天文學家經常觀察星象圖。星象圖中用平面上的點來表示一顆星星,每一顆星星都有一個笛卡爾坐標。設定星星的等級為其左下角星星的總數。天文學家們想知道星星等級的分布情況。
在這里插入圖片描述

比如上圖, 5 5 5號星星的等級為 3 3 3(其左下角有編號為 1 1 1 2 2 2 4 4 4星星共三顆)。 2 2 2號星星和 4 4 4號星星的等級為 1 1 1。在上圖中只有一顆星星等級為 0 0 0,兩顆星星等級為 1 1 1,一顆星星等級為 2 2 2,一顆星星等級為 3 3 3
給定一個星象圖,請你寫一個程序計算各個等級的星星數目。

輸入輸出格式

輸入格式:

輸入的第一行包含星星的總數 N ( 1 < = N < = 15000 ) N (1<=N<=15000) N(1<=N<=15000)。接下來 N N N行,描述星星的坐標 ( X , Y ) (X,Y) (X,Y) X X X Y Y Y用空格分開, 0 ≤ X , Y ≤ 32000 0\le X,Y\le 32000 0X,Y32000)。星象圖中的每個點處最多只有一顆星星。所有星星按 Y Y Y坐標升序排列。 Y Y Y坐標相等的星星按 X X X坐標升序排列。

輸出格式

輸出包含 N N N行,每行一個整數。第一行包含等級 0 0 0的星星數目,第二行包含等級 1 1 1的星星數目,依此類推,最后一行包含等級為 N ? 1 N-1 N?1的星星數目。

輸入輸出樣例

輸入樣例

5
1 1
5 1
7 1
3 3
5 5

輸出樣例

1
2
1
1
0

題目講解

由于輸入數據有序,所以在第 i i i顆星星左下角的星星一定在 i i i前面!!原理自己想想就知道了~~

所以其實就是求在點 i i i前面的點中,有多少個的 X X X坐標是比 i i i X X X坐標要小的,因此直接考慮插入排序做法:

步驟如下

  • 輸入星星的數量 n n n
  • 循環從 1 1 1 n n n
  • 每次輸入當前點的 X X X Y Y Y
  • 用二分查找當前點的 X X X應當放在哪個位置
  • 用變了量 f f f記錄位置, f ? 1 f-1 f?1就是當前星星的等級
  • c o p y copy copy將數據,從當前合適的位置開始,到 i ? 1 i-1 i?1往后移動一位
  • 將當前數據存入排序數組
  • 用另一個數組標記這個等級的星星 + + ++ ++
  • 循環輸出每個級別的星星

AC 代碼

#include <bits/stdc++.h>
#define N 20000
using namespace std;
int n,x,y,f,t[N],k[N];
int main() {scanf("%d",&n);for (int i=1; i<=n; i++) {scanf("%d%d",&x,&y);f=upper_bound(t+1,t+i,x)-t;copy(t+f,t+i,t+f+1);t[f]=x;k[f-1]++;}for (int i=0; i<n; i++) {printf("%d\n",k[i]);}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/43020.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/43020.shtml
英文地址,請注明出處:http://en.pswp.cn/news/43020.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HIVE SQL實現分組字符串拼接concat

在Mysql中可以通過group_concat()函數實現分組字符串拼接&#xff0c;在HIVE SQL中可以使用concat_ws()collect_set()/collect_list()函數實現相同的效果。 實例&#xff1a; abc2014B92015A82014A102015B72014B6 1.concat_wscollect_list 非去重拼接 select a ,concat_ws(-…

Linux系統中基于NGINX的代理緩存配置指南

作為一名專業的爬蟲程序員&#xff0c;你一定知道代理緩存在加速網站響應速度方面的重要性。而使用NGINX作為代理緩存服務器&#xff0c;能夠極大地提高性能和效率。本文將為你分享Linux系統中基于NGINX的代理緩存配置指南&#xff0c;提供實用的解決方案&#xff0c;助你解決在…

C語言刷題訓練DAY.8

1.計算單位階躍函數 解題思路&#xff1a; 這個非常簡單&#xff0c;只需要if else語句即可完成 解題代碼&#xff1a; #include <stdio.h>int main() {int t 0;while(scanf("%d",&t)!EOF){if (t > 0)printf("1\n");else if (t < 0)pr…

大模型基礎02:GPT家族與提示學習

大模型基礎&#xff1a;GPT 家族與提示學習 從 GPT-1 到 GPT-3.5 GPT(Generative Pre-trained Transformer)是 Google 于2018年提出的一種基于 Transformer 的預訓練語言模型。它標志著自然語言處理領域從 RNN 時代進入 Transformer 時代。GPT 的發展歷史和技術特點如下: GP…

【校招VIP】java語言類和對象之map、set集合

考點介紹&#xff1a; map、set集合相關內容是校招面試的高頻考點之一。 map和set是一種專門用來進行搜索的容器或者數據結構&#xff0c;其搜索效率與其具體的實例化子類有關系。 『java語言類和對象之map、set集合』相關題目及解析內容可點擊文章末尾鏈接查看&#xff01; …

深入了解Maven(一)

目錄 一.Maven介紹與功能 二.依賴管理 1.依賴的配置 2.依賴的傳遞性 3.排除依賴 4.依賴的作用范圍 5.依賴的生命周期 一.Maven介紹與功能 maven是一個項目管理和構建工具&#xff0c;是基于對象模型POM實現。 Maven的作用&#xff1a; 便捷的依賴管理&#xff1a;使用…

springboot 使用zookeeper實現分布式隊列

一.添加ZooKeeper依賴&#xff1a;在pom.xml文件中添加ZooKeeper客戶端的依賴項。例如&#xff0c;可以使用Apache Curator作為ZooKeeper客戶端庫&#xff1a; <dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</…

【java安全】Log4j反序列化漏洞

文章目錄 【java安全】Log4j反序列化漏洞關于Apache Log4j漏洞成因CVE-2017-5645漏洞版本復現環境漏洞復現漏洞分析 CVE-2019-17571漏洞版本漏洞復現漏洞分析 參考 【java安全】Log4j反序列化漏洞 關于Apache Log4j Log4j是Apache的開源項目&#xff0c;可以實現對System.out…

英語——構詞法

按照語言一定的規律創造新詞的方法就叫作構詞法。英語中常見的構詞法包括六種:合成法、派生法、轉化法、混合法、截短法和首尾字母結合法。其中后三種將在第四節“縮寫和簡寫”中進行講解。 第一節 合成法 英語構詞法中把兩個單詞連在一起合成一個新詞,前一個詞修飾或限定后…

前端性能優化——包體積壓縮插件,打包速度提升插件,提升瀏覽器響應的速率模式

前端代碼優化 –其他的優化可以具體在網上搜索 壓縮項目打包后的體積大小、提升打包速度&#xff0c;是前端性能優化中非常重要的環節&#xff0c;結合工作中的實踐總結&#xff0c;梳理出一些 常規且有效 的性能優化建議 ue 項目可以通過添加–report命令&#xff1a; "…

innodb索引與算法

B樹主鍵插入 B樹在innodb的插入有三種模式page_last_insert, page_dirction, page_N_direction 而在bustub里面的B樹就是page_N_direction,如果是自增主鍵的話&#xff0c;就是上面這樣的插入法 FIC優化 (DDL) 選擇性統計 覆蓋索引 MMR ICP優化 自適應hash 全文索引 MySQL…

Rust之編寫自動化測試

1、測試函數的構成&#xff1a; 在最簡單的情形下,Rust中的測試就是一個標注有test屬性的函數。屬性 (attribute)是一種用于修飾Rust代碼的元數據。只需要將#[test]添加到關鍵字fn的上一行便可以將函數轉變為測試函數。當測試編寫完成后,我們可以使用cargo test命令來運行測試…

Flink-----Standalone會話模式作業提交流程

1.Flink的Slot特點: 均分隔離內存,不隔離CPU可以共享:同一個job中,不同算子的子任務才可以共享同一個slot,同時在運行的前提是,屬于同一個slot共享組,默認都是“default”2.Slot的數量 與 并行度 的關系 slot 是一種靜態的概念,表示最大的并發上線并行度是個動態的概念…

List和ObservableCollection和ListBinding在MVVM模式下的對比

List和ObservableCollection和ListBinding在MVVM模式下的對比 List 當對List進行增刪操作后&#xff0c;并不會對View進行通知。 //Employee public class Employee : INotifyPropertyChanged {public event PropertyChangedEventHandler? PropertyChanged;public string N…

Vue-13.創建完整的Vue項目(vue+vue-cli+js)

前言 之前寫了命令創建Vue項目&#xff0c;但是事實上我們可以直接用編譯器直接創建項目&#xff0c;這里我使用webstorm&#xff08;因為我是前后端兼修的所以我習慣使用Idea家族的編譯器&#xff09; 只寫前端的推薦用VsCode前后端都寫的推薦用webstorm 新建項目 項目初始…

確保Django項目的穩定運行和持續改進

確保Django項目的穩定運行和持續改進 引言 Django是一個強大的Python Web框架&#xff0c;用于構建高效、可靠的Web應用程序。然而&#xff0c;部署一個Django項目并不意味著工作已經完成。在項目上線之后&#xff0c;確保項目的穩定運行并不斷進行改進是非常重要的。本博客將…

vscode 安裝勾選項解釋

1、通過code 打開“操作添加到windows資源管理器文件上下文菜單 &#xff1a;把這個兩個勾選上&#xff0c;可以對文件使用鼠標右鍵&#xff0c;選擇VSCode 打開。 2、將code注冊為受支持的文件類型的編輯器&#xff1a;不建議勾選&#xff0c;這樣會默認使用VSCode打開支持的相…

《Linux從練氣到飛升》No.15 Linux 環境變量

&#x1f57a;作者&#xff1a; 主頁 我的專欄C語言從0到1探秘C數據結構從0到1探秘Linux菜鳥刷題集 &#x1f618;歡迎關注&#xff1a;&#x1f44d;點贊&#x1f64c;收藏??留言 &#x1f3c7;碼字不易&#xff0c;你的&#x1f44d;點贊&#x1f64c;收藏??關注對我真的…

微信小程序通用字體代碼

下面是一個簡單的微信小程序通用字體代碼示例&#xff1a; // 在app.wxss中設置全局字體樣式 import ./styles/fonts.wxss;// 在fonts.wxss中定義字體樣式 font-face {font-family: CustomFont;src: url(font.ttf) format(truetype); }// 在page.wxss中使用自定義字體樣式 .cus…

SASS 學習筆記 II

SASS 學習筆記 II 上篇筆記&#xff0c;SASS 學習筆記 中包含&#xff1a; 配置 變量 嵌套 這里加一個擴展&#xff0c;嵌套中有一個 & 的用法&#xff0c;使用 & 可以指代當前 block 中的 selector&#xff0c;后面可以追加其他的選擇器。如當前的 scope 是 form&a…