網站首頁 編程語言 正文
有一天我用水壺燒水的時候
不小心水放滿了
于是當它燒沸騰的時候
水一直往外冒
我便想起了遞歸導致棧溢出的情況
于是阿紫姐姐便在網上學習了非遞歸算法
接下來阿紫姐姐傳授給大家哦!
本期阿紫姐姐就帶領大家一起來學習快速排序、歸并排序非遞歸的實現哦!!!
目錄:
1、快速排序非遞歸
2、歸并排序非遞歸
學習非遞歸之前我們得先學習遞歸的缺陷,才能更好了解非遞歸的優勢。
遞歸的缺陷:棧幀空間太深,棧空間不夠用,會導致溢出。
c語言內存分配:
例如:
遞歸1000次:
遞歸10000次:
圖解:
遞歸(函數調用)是進行壓棧的操作,當壓棧太深時,就會造成棧溢出的情況。
遞歸改非遞歸方法:①直接改循環 ②借助數據結構棧模擬遞歸過程
1、快速排序非遞歸
我們來運用非遞歸實現快速排序挖坑法
1.1代碼實現
棧的操作,大家可以看阿紫之前發的“不會2022年還有人不懂棧吧”這篇博文哦!
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include"stack.h"
//挖坑法 - 升序
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)
{
ST 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);//銷毀棧
}
int main()
{
int arr[10] = {3, 4, 2, 5, 1};
int sz = sizeof(arr) / sizeof(arr[0]);
QuickSortNonR(arr, sz);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
1.2思路講解
我們根據上面的代碼來學習思路
2、歸并排序非遞歸
2.1代碼實現
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include"stack.h"
//歸并排序之非遞歸
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);
}
int main()
{
int arr[] = {10, 6, 7, 1, 3, 9, 4, 2 };
int sz = sizeof(arr) / sizeof(arr[0]);
MergeSortNonR(arr, sz);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
2.2思路講解
原文鏈接:https://blog.csdn.net/m0_66488562/article/details/124248557
相關推薦
- 2022-09-26 Josephus_problem_bidirectional 雙向約瑟夫問題
- 2022-12-21 C語言中#if的使用詳解_C 語言
- 2022-09-19 Pytorch實現LSTM案例總結學習_python
- 2022-12-21 Python實現簡易計算器的示例代碼_python
- 2022-10-14 Go?Ginrest實現一個RESTful接口_Golang
- 2024-03-01 【uniapp】uniapp中刷新本頁面
- 2022-11-17 Go語言中常用的基礎方法總結_Golang
- 2023-03-15 pandas將Series轉成DataFrame的實現_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支