2024年最新快速排序和归并排序非递归的详解_快速排序分递归和非递归,2024年最新凭借这份大数据开发面试题集

文章介绍了一套覆盖95%以上大数据知识点的系统化学习资料,包括针对不同水平的学习者设计的课程、大厂面经、学习资源和视频讲解,强调非递归实现的快速排序和归并排序算法。
摘要由CSDN通过智能技术生成

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

		//归并过程中右半区间有且不多(算多了)修正一下
		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;//刚才是11一组归并,\*=2让2倍归并
}

free(tmp);

}
void TestMergeSort()
{
int a[] = { 10, 6, 7, 1, 3, 9, 4, 2 };
MergeSortNonR(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}


### 归并非递归总结


**时间复杂度还是不错的和归并排序递归是一样的都是O(N\*logN)。**


## 总代码


### Stack.h



#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <stdlib.h>
typedef int STDataType;
typedef struct Stack
{
STDataType* a;//是一个指针指向这个数组
int top;//栈顶
int capacity;//容量
}ST;

//栈需要的接口
// 初始化栈
void StackInit(ST* ps);
// 销毁栈
void StackDestory(ST* ps);
//入栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//取栈顶的数据
STDataType StackTop(ST* ps);
//栈的数据个数
int StackSize(ST* ps);
//检测栈是否为空,如果为空返回非零结果,如果非空返回0
bool StackEmpty(ST* ps);//用布尔来判断真假更好用,但是注意引用头文件


### Stack.c



#include"Stack.h"

void StackInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
printf(“malloc fail\n”);
exit(-1);
}
ps->capacity = 4;
ps->top = 0;
}

void StackDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}

void StackPush(ST* ps, STDataType x)
{
assert(ps);

//满了怎么办?---增容
if (ps->top == ps->capacity)
{
	STDataType\* tmp = (STDataType\*)realloc(ps->a, ps->capacity \* 2 \* sizeof(STDataType));
	if (tmp == NULL)
	{
		printf("realloc fail\n");
		exit(-1);
	}
	else
	{
		ps->a = tmp;
		ps->capacity \*= 2;//乘等2才会变成它的二倍
	}
}

ps->a[ps->top] = x;
ps->top++;

}

void StackPop(ST* ps)
{
assert(ps);
//栈空了,调用pop,直接中止程序并报错
assert(ps->top > 0);

ps->top--;

}

STDataType StackTop(ST* ps)
{
assert(ps);
//栈空了,调用top,直接中止程序并报错
assert(ps->top > 0);

return ps->a[ps->top - 1];

}

int StackSize(ST* ps)
{
assert(ps);

return ps->top;//top所在数组的下标就是栈的长度

}

bool StackEmpty(ST* ps)
{
assert(ps);

return ps->top == 0;//如果为空返回非零结果,如果不为空返回0

}


### Sort.c


**这里因为快速排序非递归中用到了单趟排序,所以直接在拷贝了一份挖坑法的单趟排序,不理解的可以去看《八大排序》(下)**



#include"Stack.h"
void PrintArray(int* a, int n)
{
for (int i = 0; i < n; ++i)
{
printf(“%d “, a[i]);
}
printf(”\n”);
}
//交换
void Swap(int* p1, int* p2)
{
int* tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
//三数取中–为了解决我们key选择的数不是最大,也不是最小的
int GetMidIndex(int* a, int left, int right)
{
int mid = (left + right) >> 1;
if (a[left] < a[mid])//如果左小于中间
{
if (a[mid] > a[right])//如果左小于中间,中间大于右,则返回中间
{
return mid;
}
else if (a[left] > a[right])//如果左小于中间,左大于右,则返回左
{
return left;
}
else
{
return right;//如果左小于中间,中间大于右,则返回右
}
}
else //a[left] > a[mid]
{
if (a[mid] > a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return left;
}
else
{
return right;
}
}
}
int PartSort1(int* a, int left, int right)
{
int index = GetMidIndex(a, left, right);//三数取中
//Swap(&a[left], &a[index]);
int begin = left, end = right;
int pivot = begin;
int key = a[begin];
//单趟排序
//单趟排序时间复杂度是O(N)-begin从左向右走,end从右向左走
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的左边,大的放到pivot的右边后,把key的值放到数组pivot的位置
pivot = begin;
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);
StackPop(&st);

	int right = StackTop(&st);
	StackPop(&st);

	//单趟排选谁无所谓
	int keyIndex = PartSort1(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);//栈销毁
//非递归中malloc的空间是在操作系统的堆上面的,因为堆很大,所以空间并没有什么影响,
//malloc的空间是在操作系统上的,与数据结构的栈(栈和队列)和堆(二叉树)没有关系

}
void TestQuickSort()
{
int a[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
QuickSortNonR(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}

//归并排序——非递归
//时间复杂度是O(N*logN)
void MergeSortNonR(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);

int gap = 1;//每组数据个数
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;//刚才是11一组归并,\*=2让2倍归并
}

free(tmp);

}
void TestMergeSort()
{
int a[] = { 10, 6, 7, 1, 3, 9, 4, 2 };
MergeSortNonR(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}

int main()
{
printf(“快速排序-非递归:”);
TestQuickSort();

printf("归并排序-非递归:");
TestMergeSort();
return 0;

}


## 结语


**熬夜写的,写着写着脑子就不太灵光了,懵懵的😩😩😩文章中有错误欢迎大家积极指出哦😚😚😚**



![img](https://img-blog.csdnimg.cn/img_convert/23e07593cc5be815d8afdc435d40fcea.png)
![img](https://img-blog.csdnimg.cn/img_convert/d6492e0b09ff5c6f88f95a8278f8dc56.png)
![img](https://img-blog.csdnimg.cn/img_convert/8c9c368bf488be29107edd54198b3e5a.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

`

## 结语


**熬夜写的,写着写着脑子就不太灵光了,懵懵的😩😩😩文章中有错误欢迎大家积极指出哦😚😚😚**



[外链图片转存中...(img-2ARkZOaO-1714919369266)]
[外链图片转存中...(img-6aUIUQ0X-1714919369266)]
[外链图片转存中...(img-Tw6ZEH4x-1714919369266)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

  • 25
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值