Sorting is recursive, it's a pity not to learn non-recursion

One day when I boiled water in a kettle

Accidentally filled with water

So when it boils

water keeps coming out

I remembered the situation where recursion caused stack overflow

So sister Azi learned the non-recursive algorithm on the Internet

Next, sister Azi will teach you all!


In this issue, Sister Azi will lead you to learn the non-recursive implementation of quick sort and merge sort! ! !

content:

1. Quick sort is non-recursive

2. Merge sort is non-recursive

Before learning about non-recursion, we have to learn about the pitfalls of recursion to better understand the advantages of non-recursion.

Defects of recursion: the stack frame space is too deep, and the stack space is not enough, which will lead to overflow.

 C language memory allocation: 

 E.g:

Recursively 1000 times:

Recursively 10000 times:  

Diagram: 

 Recursion (function call) is the operation of pushing the stack. When the stack is pushed too deep, it will cause a stack overflow.


Recursive to non-recursive method: ①Directly change the loop ②Use the data structure stack to simulate the recursive process 

 1. Quick sort is non-recursive 

Let's use the non-recursive implementation of quicksort digging 

 1.1 Code Implementation

For the operation of the stack, you can read the blog post "No one will understand the stack in 2022" previously posted by A Zi!

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#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 Explanation of ideas

 Let's learn ideas based on the above code 

 

 2. Merge sort is non-recursive

2.1 Code Implementation

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#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 Explanation of ideas

 

 

 

Guess you like

Origin blog.csdn.net/m0_66488562/article/details/124248557