<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
建議還不理解快速排序和歸併排序的小夥伴們可以先去看我上一篇部落格哦!C語言超詳細講解排序演演算法下篇
我們先簡單來了解下記憶體分佈結構:
棧區:用於存放地址、臨時變數等;
堆區:程式執行期間動態分配所使用的場景;
靜態區:存放全域性變數和靜態變數,具體還分為 .bss段和.data段;
.bss段:存放未初始化的和初始化為0的全域性變數或者靜態變數;
.data段:初始化不為0的全域性變數或者靜態變數;
常數區:存放常數(比如比變數名字,非0的初始化值,const常數,字串等),唯讀;
程式碼區:存放程式碼的位置,唯讀;
我們再來看這樣的一串程式碼執行的結果:
這是一個累加求和的遞迴函數,當我們發現累加求和到1000遞迴仍然能正常執行,我們接著改為10000看看是否還能正常執行?
我們可以看到,當數值達到10000的時候程式已經崩了,並不會顯示任何錯誤,當我們進入偵錯可以發現報錯顯示棧溢位,那為什麼會造成棧溢位呢,我們接著往下看!
遞迴的基本認識:
遞迴本質也是函數呼叫,是函數呼叫,本質就要形成和釋放棧幀
呼叫函數是有成本的,這個成本就體現在形成和釋放棧幀上:時間+空間
所以,遞迴就是不斷形成棧幀的過程
記憶體和CPU的資源是有限的,也就決定了,合理的遞迴是絕對不能無限遞迴下去,如果遞迴呼叫深度太深,這樣有可能導致一 直開闢棧空間,最終產生棧空間耗盡的情況,這樣的現象我們稱為棧溢位!
既然使用遞迴極端情況下會出現棧溢位的問題,那麼我們就用非遞迴的方式來實現快速排序和歸併排序!
快速排序非遞迴實現思想:
首先我們可以藉助資料結構的棧來完成,遵循棧的後進先出,我們可以先入右再入左,然後使用我們上一期講的三個方法中的其中一個方法,這裡我們選擇挖坑法,使用挖坑法我們可以看作成兩個區間也就是: [left, keyIndex - 1] 和 [keyIndex + 1, right],如果區間存在我們接著入棧,如此迴圈直到棧為空,則排序結束!
圖解見下:
程式碼實現如下:
//挖坑法 - 升序 int PartSort(int* a, int left, int right) { int begin = left; int end = right; int key = a[begin]; int pivot = begin; while (begin < end) { while (begin < end && a[end] >= key) { --end; } a[pivot] = a[end]; pivot = end; while (begin < end && a[begin] <= key) { ++begin; } a[pivot] = a[begin]; pivot = begin; } pivot = begin;//當begin與end相遇,隨便把begin和end的值給pivot a[pivot] = key; return pivot; } void QuickSortNonR(int* a, int n) { Stack st; StackInit(&st);//初始化棧 StackPush(&st, n - 1);//入陣列最後一個元素下標 StackPush(&st, 0);//入陣列第一個元素下標 while (!StackEmpty(&st))//當棧不為空我們就進入迴圈 { int left = StackTop(&st);//取出棧頂元素給left StackPop(&st);//出棧 - 刪除棧頂元素 int right = StackTop(&st); StackPop(&st); int keyIndex = PartSort(a, left, right);//使用挖坑法區間排序 //[left, keyIndex - 1] keyIndex [keyIndex + 1, right] - 分成子區間 if (keyIndex + 1 < right)//因棧後進先出的特性,所以先入右區間 { StackPush(&st, right); StackPush(&st, keyIndex + 1); } if (left < keyIndex - 1) { StackPush(&st, keyIndex - 1); StackPush(&st, left); } } StackDestory(&st);//銷燬棧 }
歸併排序非遞迴實現思想:
上期我們知道歸併需要開闢一個陣列,並且使用分治的演演算法來實現歸併排序,而非遞迴版本我們的思路也是差不多,先讓他們一個一個歸併,然後兩個兩個歸併,再接著四個四個一起歸併,具體圖解見下:
程式碼實現如下:
void MergeSortNonR(int* a, int n) { int* tmp = (int*)malloc(sizeof(int) * n); if (tmp == NULL) { perror("malloc:"); return; } int gap = 1;//gap為每組資料的個數,每次翻倍 while (gap < n) { for (int i = 0; i < n; i += 2 * gap) { //可以看成 [i, i + gap - 1] [i + gap, i + 2 * gap - 1] int begin1 = i, end1 = i + gap - 1; int begin2 = i + gap, end2 = i + 2 * gap - 1; //歸併過程中右半區間有可能不存在! if (begin2 >= n) break; //歸併過程中右半區間越界了,就修正下 if (end2 >= n) { end2 = n - 1; } int index = i; while (begin1 <= end1 && begin2 <= end2) { if (a[begin1] < a[begin2]) { tmp[index++] = a[begin1++]; } else { tmp[index++] = a[begin2++]; } } while (begin1 <= end1) { tmp[index++] = a[begin1++]; } while (begin2 <= end2) { tmp[index++] = a[begin2++]; } //拷貝進去 for (int j = i; j <= end2; ++j) { a[j] = tmp[j]; } } gap *= 2; } free(tmp); }
本期到這裡就結束了,相信你們已經對非遞迴快速排序和歸併排序已經很瞭解了,非遞迴這兩個在校招中經常會考,加油把!
gitee(碼雲):Mercury. (zzwlwp) - Gitee.com
到此這篇關於C語言非遞迴演演算法解決快速排序與歸併排序產生的棧溢位的文章就介紹到這了,更多相關C語言 棧溢位內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45