網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
一、前言
分治算法
歸并排序,其實(shí)就是一種分治算法 ,那么在了解歸并排序之前,我們先來(lái)看看什么是分治算法。在算法設(shè)計(jì)中,我們引入分而治之的策略,稱為分治算法,其本質(zhì)就是將一個(gè)大規(guī)模的問(wèn)題分解為若干個(gè)規(guī)模較小的相同子問(wèn)題,分而治之。
分治算法解題方法
1.分解:
將要解決的問(wèn)題分解為若干個(gè)規(guī)模較小、相互獨(dú)立、與原問(wèn)題形式相同的子問(wèn)題。
2.治理:
求解各個(gè)子問(wèn)題。由于各個(gè)子問(wèn)題與原問(wèn)題形式相同,只是規(guī)模較小而已,而當(dāng)子問(wèn)題劃分得足夠小時(shí),就可以用簡(jiǎn)單的方法解決。
3.合并
按原問(wèn)題的要求,將子問(wèn)題的解逐層合并構(gòu)成原問(wèn)題的解。
二、歸并排序
1.問(wèn)題分析
歸并排序是比較穩(wěn)定的排序方法。它的基本思想是把待排序的元素分解成兩個(gè)規(guī)模大致相等的子序列。如果不易分解,將得到的子序列繼續(xù)分解,直到子序列中包含的元素個(gè)數(shù)為1。因?yàn)閱蝹€(gè)元素的序列本身就是有序的,此時(shí)便可以進(jìn)行合并,從而得到一個(gè)完整的有序序列。
2.算法設(shè)計(jì)
(1)分解:
將待排序的元素分成大小大致一樣的兩個(gè)子序列。
(2)治理:
對(duì)兩個(gè)子序列進(jìn)行個(gè)并排序。
(3)合并:
將排好序的有序子序列進(jìn)行合并,得到最終的有序序列。
3.算法分析
首先我們先給定一個(gè)無(wú)序的數(shù)列(42,15,20,6,8,38,50,12),我們進(jìn)行合并排序數(shù)列,如下圖流程圖所示:
步驟一:首先將待排序的元素分成大小大致相同的兩個(gè)序列。
步驟二:再把子序列分成大小大致相同的兩個(gè)子序列。
步驟三:如此下去,直到分解成一個(gè)元素停止,這時(shí)含有一個(gè)元素的子序列都是有序的。
步驟四:進(jìn)行合并操作,將兩個(gè)有序的子序列合并為一個(gè)有序序列,如此下去,直到所有的元素都合并為一個(gè)有序序列。
舉例,下面我將以序列(4,9,15,24,30,2,6,18,20)進(jìn)行圖解。
(1)初始化:i = low,j = mid+1,mid = (low+hight)/2 ,申請(qǐng)一個(gè)輔助數(shù)組 b
int* b = new int[hight - low + 1]; //用 new 申請(qǐng)一個(gè)輔助函數(shù)
int i = low, j = mid + 1, k = 0; // k為 b 數(shù)組的小標(biāo)
?(2)現(xiàn)在比較 a [i]? 和 b[j]? ,將較小的元素放在 b 數(shù)組中,相應(yīng)的指針向后移動(dòng),直到 i > mid 或者 j>hight 時(shí)結(jié)束。
while (i <= mid && j <= hight)
{
if (a[i] <= a[j])
{
b[k++] = a[i++]; //按從小到大存放在 b 數(shù)組里面
}
else
{
b[k++] = a[j++];
}
}
進(jìn)行第一次比較 a[i]=4? 和 a[j]=2,將較小的元素 2 放入數(shù)組? b? 中,j++,k++,如下圖:
進(jìn)行第二次比較 a[i]=4? 和 a[j]=6,將較小的元素放 4 入數(shù)組? b? 中,i++,k++,如下圖:
進(jìn)行第三次比較 a[i]=9??和 a[j]=6,將較小的元素放 6?入數(shù)組? b? 中,j++,k++,如下圖:
進(jìn)行第四次比較 a[i]=9??和 a[j]=18,將較小的元素放 9?入數(shù)組? b? 中,i++,k++,如下圖:
進(jìn)行第五次比較 a[i]=15? 和 a[j]=18,將較小的元素放 15?入數(shù)組? b? 中,i++,k++,如下圖:
進(jìn)行第六次比較 a[i]=24? 和 a[j]=18,將較小的元素放 18?入數(shù)組? b? 中,j++,k++,如下圖:
進(jìn)行第七次比較 a[i]=24? 和 a[j]=20,將較小的元素放 20?入數(shù)組? b? 中,j++,k++,如下圖:
此時(shí),j>hight 了,while循環(huán)結(jié)束,但 a?數(shù)組還剩下元素(i<mid)可直接放入? b? 數(shù)組就可以了。如下圖所示:
while (i <= mid) // j 序列結(jié)束,將剩余的 i 序列補(bǔ)充在 b 數(shù)組中
{
b[k++] = a[i++];
}
while (j <= hight)// i 序列結(jié)束,將剩余的 j 序列補(bǔ)充在 b 數(shù)組中
{
b[k++] = a[j++];
}
現(xiàn)在將? b? 數(shù)組的元素賦值給 a 數(shù)組,再將 b? 數(shù)組銷(xiāo)毀,即可。
for (int i = low; i <= hight; i++) //將 b 數(shù)組的值傳遞給數(shù)組 a
{
a[i] = b[k++];
}
delete[]b; // 輔助數(shù)組用完后,將其的空間進(jìn)行釋放(銷(xiāo)毀)
(3)遞歸的形式進(jìn)行歸并排序
void mergesort(int* a, int low, int hight) //歸并排序
{
if (low < hight)
{
int mid = (low + hight) / 2;
mergesort(a, low, mid); //對(duì) a[low,mid]進(jìn)行排序
mergesort(a, mid + 1, hight); //對(duì) a[mid+1,hight]進(jìn)行排序
merge(a, low, mid, hight); //進(jìn)行合并操作
}
}
三、AC代碼
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
void merge(int* a, int low, int mid, int hight) //合并函數(shù)
{
int* b = new int[hight - low + 1]; //用 new 申請(qǐng)一個(gè)輔助函數(shù)
int i = low, j = mid + 1, k = 0; // k為 b 數(shù)組的小標(biāo)
while (i <= mid && j <= hight)
{
if (a[i] <= a[j])
{
b[k++] = a[i++]; //按從小到大存放在 b 數(shù)組里面
}
else
{
b[k++] = a[j++];
}
}
while (i <= mid) // j 序列結(jié)束,將剩余的 i 序列補(bǔ)充在 b 數(shù)組中
{
b[k++] = a[i++];
}
while (j <= hight)// i 序列結(jié)束,將剩余的 j 序列補(bǔ)充在 b 數(shù)組中
{
b[k++] = a[j++];
}
k = 0; //從小標(biāo)為 0 開(kāi)始傳送
for (int i = low; i <= hight; i++) //將 b 數(shù)組的值傳遞給數(shù)組 a
{
a[i] = b[k++];
}
delete[]b; // 輔助數(shù)組用完后,將其的空間進(jìn)行釋放(銷(xiāo)毀)
}
void mergesort(int* a, int low, int hight) //歸并排序
{
if (low < hight)
{
int mid = (low + hight) / 2;
mergesort(a, low, mid); //對(duì) a[low,mid]進(jìn)行排序
mergesort(a, mid + 1, hight); //對(duì) a[mid+1,hight]進(jìn)行排序
merge(a, low, mid, hight); //進(jìn)行合并操作
}
}
int main()
{
int n, a[100];
cout << "請(qǐng)輸入數(shù)列中的元素個(gè)數(shù) n 為:" << endl;
cin >> n;
cout << "請(qǐng)依次輸入數(shù)列中的元素:" << endl;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
mergesort(a, 0, n-1);
cout << "歸并排序結(jié)果" << endl;
for (int i = 0; i < n; i++)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
原文鏈接:https://blog.csdn.net/weixin_45031801/article/details/127034720
相關(guān)推薦
- 2022-05-14 一起來(lái)學(xué)習(xí)React元素的創(chuàng)建和渲染_React
- 2022-08-05 linux安裝部署lua環(huán)境
- 2023-04-03 Python調(diào)試神器之PySnooper的使用教程分享_python
- 2022-07-04 反向傳播BP學(xué)習(xí)算法Gradient?Descent的推導(dǎo)過(guò)程_相關(guān)技巧
- 2022-02-21 C#多線程學(xué)習(xí)之Thread、ThreadPool、Task、Parallel四者區(qū)別_C#教程
- 2022-04-09 Python調(diào)用win10toast框架實(shí)現(xiàn)定時(shí)調(diào)起系統(tǒng)通知_python
- 2022-11-30 Python利用yarl實(shí)現(xiàn)輕松操作url_python
- 2023-01-31 React受控組件與非受控組件深入講解_React
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支