国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【排序算法】歸并排序(C語言)

這篇具有很好參考價值的文章主要介紹了【排序算法】歸并排序(C語言)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【排序算法】—— 歸并排序(C語言)

一、歸并排序的原理

歸并排序(MergeSort) 是建立在歸并操作上的一種有效的排序算法,采用分治法排序,分為分解、合并兩個步驟。

分解:將數(shù)組分割成兩個數(shù)組,再分別將兩個數(shù)組又細分成2個數(shù)組,直到,最后每個數(shù)組都是一個元素,這時將該單元素數(shù)組看為有序數(shù)組

合并:將分割的有序數(shù)組進行排序,排成有序數(shù)組后繼續(xù)為上一個分割它的數(shù)組合并,直到數(shù)組被合并成原來的數(shù)組,此時已經(jīng)排好序了

【排序算法】歸并排序(C語言)

二、兩個有序數(shù)組排序和合并

1. 原地排序

從頭到尾遍歷,選最小值放前面

  1. 合并的兩個數(shù)組是一個數(shù)組分割開的,所以它們的首尾是相連的,用箭頭i指向合并后數(shù)組的當前下標位置

【排序算法】歸并排序(C語言)

  1. 將2和1比較,1小,所以將1賦值給合并后數(shù)組的第一個元素,此時我們發(fā)現(xiàn),數(shù)組arr1的首元素被覆蓋,所以不能直接賦值

【排序算法】歸并排序(C語言)

  1. 若是將arr1的元素向后挪動一格,則數(shù)據(jù)正常,但是效率太低,不可取

【排序算法】歸并排序(C語言)

從后往前遍歷,選最大值放后面

  1. 用箭頭i指向合并后數(shù)組的后邊,從后往前遍歷

【排序算法】歸并排序(C語言)

  1. 8比7大,賦值給i指向的位置,此時7被覆蓋,不行

【排序算法】歸并排序(C語言)

  1. 若是將7和8交換呢,看樣子可以,那如果是如下數(shù)組就不行了,arr1的有序性被破壞,不能繼續(xù)這樣排序了

【排序算法】歸并排序(C語言)

2. 創(chuàng)建臨時空間

  1. 既然無法原地排序,那我們創(chuàng)建臨時空間,對兩個有序數(shù)組排序

【排序算法】歸并排序(C語言)

  1. 從前往后遍歷,選出最小值放在temp數(shù)組前面部分

【排序算法】歸并排序(C語言)

  1. 直到排序完成,將temp數(shù)組中的數(shù)據(jù)拷貝回原數(shù)組,arr1arr2就合并成為有序數(shù)組arr

【排序算法】歸并排序(C語言)

二、遞歸實現(xiàn)

我們使用遞歸來實現(xiàn)數(shù)組的分割和合并,它的邏輯非常像二叉樹的后序遍歷,由于我們要使用遞歸,又要申請臨時空間,所以我們先申請好臨時空間,再將歸并排序過程作為子函數(shù)調(diào)用,這樣不用在每次遞歸過程申請釋放空間

歸并排序調(diào)用遞歸

void MergeSort(int* arr, int size)
{
	int* temp = (int*)malloc(size * sizeof(int));
	if (temp == NULL)
	{
		perror("malloc fail\n");
		return;
	}

	_MergeSort(arr, 0, size - 1, temp);	//歸并排序的過程

	free(temp);
	temp = NULL;
}

歸并排序

由于我們遞歸過程中要用區(qū)間來分割函數(shù),所以參數(shù)為待排數(shù)組的閉區(qū)間,使代碼書寫更加方便,這也是將遞歸過程單獨調(diào)用的好處

void _MergeSort(int* arr, int left, int right, int* temp)
{
    //分解:
    //分割數(shù)組只有一個元素時停止遞歸
	if (left >= right)
	{
		return;
	}

	int mid = (left + right) / 2;

	_MergeSort(arr, left, mid, temp);		//分割并排序數(shù)組左半邊
	_MergeSort(arr, mid + 1, right, temp);	//分割并排序數(shù)組右半邊

    //合并:
	int begin1 = left, end1 = mid;			//數(shù)組1的左右區(qū)間
	int begin2 = mid + 1, end2 = right;		//數(shù)組2的左右區(qū)間
	int i = begin1;

    //排序兩個有序數(shù)組
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (arr[begin1] <= arr[begin2])
		{
			temp[i] = arr[begin1];
			begin1++;
		}
		else
		{
			temp[i] = arr[begin2];
			begin2++;
		}
		i++;
	}

	while (begin1 <= end1)
	{
		temp[i] = arr[begin1];
		begin1++;
		i++;
	}

	while (begin2 <= end2)
	{
		temp[i] = arr[begin2];
		begin2++;
		i++;
	}

	//拷貝臨時數(shù)組的內(nèi)容到原數(shù)組(可以調(diào)用memcpy函數(shù))
	//memcpy(arr+left, temp+left, (right-left+1)*sizeof(int));
	for (i = left; i <= right; i++)
	{
		arr[i] = temp[i];
	}
}

三、非遞歸實現(xiàn)

歸并排序的非遞歸實現(xiàn)是非常復雜的一個算法,在快速排序中我們使用棧來存儲待排數(shù)組的左右區(qū)間,模擬遞歸的過程。但是在歸并排序中我們不這么實現(xiàn)。

1. 實現(xiàn)思路

由于數(shù)組總是以一半的方式進行分割,分割的終點是每個數(shù)組只有一個元素,所以我們可以定義一個變量gap作為分割后數(shù)組的長度,遍歷時一次跳過gap * 2個元素,剛好是兩個數(shù)組的長度,gap從1開始對兩個有序數(shù)組進行排序,直到gap作為數(shù)組長度的一半時結束

  1. gap = 1,此時將長度為1的數(shù)組排序并合并,將兩個長度為1的數(shù)組合并(黃色和藍色分別是需要合并的兩個數(shù)組)

【排序算法】歸并排序(C語言)

  1. 排序合并后,將i指針向后移動gap * 2個元素,剛好兩個數(shù)組,繼續(xù)排序合并

【排序算法】歸并排序(C語言)

  1. 持續(xù)上述操作,直到數(shù)組排序完成,則第一躺排序完成,所有長度為1的有序數(shù)組都合并成長度為2的有序數(shù)組

【排序算法】歸并排序(C語言)

  1. gap *= 2,一個數(shù)組長度為2,然后遍歷數(shù)組,一次跳過2個有序數(shù)組(4個元素),并將兩個有序數(shù)組排序合并

【排序算法】歸并排序(C語言)

  1. gap *= 2,一個數(shù)組長度為4,然后遍歷數(shù)組,一次跳過2個有序數(shù)組(8個元素),并將兩個有序數(shù)組排序合并

【排序算法】歸并排序(C語言)

  1. gap *= 2,此時gap為8,等于數(shù)組長度,意味著沒有第二個數(shù)組與長度為8的數(shù)組合并了,排序結束,數(shù)組有序

【排序算法】歸并排序(C語言)

2. 數(shù)組邊界問題

在歸并排序的非遞歸實現(xiàn)中,我們要遍歷數(shù)組,將兩個長度為gap的數(shù)組排序合并,但是gap總是2的冪次方,這就導致數(shù)組長度不一定是gap * 2的倍數(shù),這就導致兩個數(shù)組在遍歷到數(shù)組邊界時會導致越界問題。所以我們要對數(shù)組的邊界問題進行處理

對于歸并排序合并的兩個數(shù)組,有3種越界情況:

  1. 第一個數(shù)組越界

黃色和藍色數(shù)組是需要合并的兩個數(shù)組,第一個數(shù)組指的是黃色數(shù)組,第二個數(shù)組指的是藍色數(shù)組

此時遍歷到數(shù)組末尾時,第一個數(shù)組只有一個元素,但是需要合并的數(shù)組長度是2,所以第一個數(shù)組訪問時會造成越界(第二個數(shù)組自然也越界)

【排序算法】歸并排序(C語言)

  1. 第二個數(shù)組全部越界

此時遍歷到數(shù)組末尾時,第一個數(shù)組的長度剛好到原數(shù)組的末尾,第二個數(shù)組不存在,訪問第二個數(shù)組是回越界

【排序算法】歸并排序(C語言)

  1. 第二個數(shù)組部分越界

此時第一個數(shù)組在數(shù)組內(nèi),第二個數(shù)組只有一部分在數(shù)組內(nèi),第二個數(shù)組存在但是長度沒有gap,訪問第二個數(shù)組時會越界

【排序算法】歸并排序(C語言)

解決方法:

我們來解決這些數(shù)組越界問題的方法是調(diào)整數(shù)組區(qū)間范圍

  1. 第一個數(shù)組越界時,第二個數(shù)組不存在,所以不用合并,第一個數(shù)組本身就是有序數(shù)組
  2. 第二個數(shù)組完全越界時,第二個數(shù)組依然不存在,所以不用合并
  3. 第三個數(shù)部分組越界時,第二個數(shù)組存在但是不完整,此時我們將第二個數(shù)組的結束位置調(diào)整為原數(shù)組末尾位置即可,讓第一個數(shù)組和第二個數(shù)組合并。

3. 代碼實現(xiàn)

先申請臨時空間,然后根據(jù)gap遍歷數(shù)組,依次排序合并數(shù)組。文章來源地址http://www.zghlxwxcb.cn/news/detail-480357.html

void MergeSortNonR(int* arr, int size)
{
    //申請空間
    int* temp = (int*)malloc(size * sizeof(int));
    if (temp == NULL)
    {
        perror("malloc fail!\n");
        return;
    }
    
    //歸并排序
    int gap = 1;
    while (gap < size)
    {
        //單趟排序
        int i = 0;
        for (i = 0; i < size; i += 2*gap)	//一次跨2*gap格,兩個數(shù)組
        {
            int begin1 = i, end1 = i+gap-1;			//第一個數(shù)組下標區(qū)間
            int begin2 = i+gap, end2 = i+2*gap-1;	//第二個數(shù)組下標區(qū)間,別忘記加上i
            
            //數(shù)組邊界處理
            if (end1 >= size)	//第一個數(shù)組越界
            {
                break;
            }
            if (begin2 >= size)	//第二個數(shù)組全部越界
            {
                break;
            }
            if (end2 >= size)	//第二個數(shù)組部分越界
            {
                end2 = size - 1;
            }
            
            //排序合并
            int j = i;	//合并后數(shù)組的下標
            while (begin1 <= end1 && begin2 <= end2)
            {
                if (arr[begin1] <= arr[begin2])
                {
                    temp[j] = arr[begin1];
                    begin1++;
                }
                else
                {
                    temp[j] = arr[begin2];
                    begin2++;
                }
                j++;
            }
            
            while (begin1 <= end1)
            {
                temp[j] = arr[begin1];
                begin1++;
                j++;
            }
            
            while (begin2 <= end2)
            {
                temp[j] = arr[begin2];
                begin2++;
                j++;
            }
            
            //拷貝temp數(shù)組到原數(shù)組(排哪個區(qū)間就拷貝哪個區(qū)間,end2是閉區(qū)間哦)
            for (j=i; j<=end2; j++)
            {
                arr[j] = temp[j];
            }
        }
        gap *= 2;
    }
    
    free(temp);
    temp = NULL;
}

到了這里,關于【排序算法】歸并排序(C語言)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • C語言實現(xiàn)八大排序算法(詳解插入排序、希爾排序、選擇排序、堆排序、冒泡排序、快速排序(遞歸和非遞歸)、歸并排序(遞歸和非遞歸)和計數(shù)排序)

    C語言實現(xiàn)八大排序算法(詳解插入排序、希爾排序、選擇排序、堆排序、冒泡排序、快速排序(遞歸和非遞歸)、歸并排序(遞歸和非遞歸)和計數(shù)排序)

    本篇文章使用C語言實現(xiàn)了數(shù)據(jù)結構中常見的八大排序算法,它們分別是 插入排序、希爾排序、選擇排序、堆排序、冒泡排序、快速排序、歸并排序和計數(shù)排序 。在排序算法的實現(xiàn)過程中,每種算法都有其獨特的特點和適用場景。插入排序通過逐步構建有序序列來排序,希爾

    2024年01月24日
    瀏覽(23)
  • 【數(shù)據(jù)結構與算法】歸并排序詳解:歸并排序算法,歸并排序非遞歸實現(xiàn)

    【數(shù)據(jù)結構與算法】歸并排序詳解:歸并排序算法,歸并排序非遞歸實現(xiàn)

    歸并排序是一種經(jīng)典的排序算法,它使用了分治法的思想。下面是歸并排序的算法思想: 遞歸地將數(shù)組劃分成較小的子數(shù)組,直到每個子數(shù)組的長度為1或者0。 將相鄰的子數(shù)組合并,形成更大的已排序的數(shù)組,直到最終得到一個完全排序的數(shù)組。 歸并排序的過程可以分為三

    2024年01月22日
    瀏覽(32)
  • 考研算法31天:歸并排序 【歸并排序,分治】

    考研算法31天:歸并排序 【歸并排序,分治】

    算法介紹 歸并算法其過程分為三步: 1.分:遞歸到最下面 2.治:兩個元素之間排序。 3。歸:遞歸到最下層然后返回,從兩個元素變成四個元素再排序。 如下圖所示: 動態(tài)圖如下: 算法題目 算法ac代碼:

    2024年02月11日
    瀏覽(22)
  • 【排序】歸并排序(C語言實現(xiàn))

    【排序】歸并排序(C語言實現(xiàn))

    ? ? ? 歸并排序(MERGE - SORT)是建立在歸并操作上的一種有效的排序算法, 該算法是采用分治法(Divide andConquer)的一個非常典型的應用。將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為

    2024年02月02日
    瀏覽(24)
  • 【排序算法】歸并排序與快速排序

    【排序算法】歸并排序與快速排序

    ??? ??????? 歡迎來到小林的博客?。??????????博客主頁:??小林愛敲代碼 ?????????博客專欄:?? 算法訓練筆記 ?????????社區(qū) :?? 進步學堂 ?????????歡迎關注:??點贊??收藏??留言 今天給大家分享兩種排序,一種是

    2024年01月19日
    瀏覽(50)
  • 【算法】排序——歸并排序和計數(shù)排序

    【算法】排序——歸并排序和計數(shù)排序

    ?========================================================================= 主頁點擊直達:個人主頁 我的小倉庫:代碼倉庫 C語言偷著笑:C語言專欄 數(shù)據(jù)結構挨打小記: 初階數(shù)據(jù)結構專欄 Linux被操作記: Linux專欄 LeetCode刷題掉發(fā)記: LeetCode刷題 算法頭疼記: 算法專欄? ========================

    2024年02月08日
    瀏覽(27)
  • 【初階算法4】——歸并排序的詳解,及其歸并排序的擴展

    【初階算法4】——歸并排序的詳解,及其歸并排序的擴展

    目錄 前言 學習目標: 學習內(nèi)容: 一、介紹歸并排序 1.1 歸并排序的思路 1.2 歸并排序的代碼 1.2.1 mergesort函數(shù)部分? 1.2.2 process函數(shù)部分? 1.2.3 merge函數(shù)部分? 二、AC兩道經(jīng)典的OJ題目 題目一:逆序?qū)栴} 題目二:小和問題? 三、練習一道LeetCode的題目 四、總結在什么情況下使

    2024年02月08日
    瀏覽(44)
  • 算法基礎15 —— 分治算法(歸并排序 + 快速排序)

    算法基礎15 —— 分治算法(歸并排序 + 快速排序)

    分治法的基本概念、思想 分治法是一種很重要的算法。 字面解釋,分治分治,分而治之。就是把一個復雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題……直到最后子問題可以簡單的直接求解,原問題的解即子問題的解的合并。 不難發(fā)現(xiàn),分

    2024年02月03日
    瀏覽(22)
  • 排序算法之【歸并排序】

    排序算法之【歸并排序】

    ?? 作者簡介:? 清水加冰,目前大二在讀,正在學習C/C++、Python、操作系統(tǒng)、數(shù)據(jù)庫等。 ?? 相關專欄: C語言初階、C語言進階、C語言刷題訓練營、數(shù)據(jù)結構刷題訓練營、有感興趣的可以看一看。 歡迎點贊 ?? 收藏 ?留言 ?? 如有錯誤還望各路大佬指正! ?每一次努力都

    2024年02月07日
    瀏覽(16)
  • 排序算法:歸并排序(非遞歸)

    排序算法:歸并排序(非遞歸)

    先贊后看,養(yǎng)成習慣?。。 _ ^3 ?? ?? ?? 碼字不易,大家的支持就是我堅持下去的動力。點贊后不要忘了 關注 我哦! 所屬專欄:排序算法 步驟如下: 1.先兩兩歸并,兩個為一組 2.然后根據(jù)每組的距離gap,分配組數(shù)進行排序 3.gap每次擴大2的倍數(shù) 4.注意一些細節(jié):首先注

    2024年03月24日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包