日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

排序會了遞歸,不學非遞歸太可惜了

作者:拼命阿紫 更新時間: 2022-04-23 編程語言

有一天我用水壺燒水的時候

不小心水放滿了

于是當它燒沸騰的時候

水一直往外冒

我便想起了遞歸導致棧溢出的情況

于是阿紫姐姐便在網上學習了非遞歸算法

接下來阿紫姐姐傳授給大家哦!



本期阿紫姐姐就帶領大家一起來學習快速排序、歸并排序非遞歸的實現哦!!!

目錄:

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

欄目分類
最近更新