笔记——排序

1、直接插入(对于基本有序的数组时,最优选👍)

1)默认第一个数据已完成排序
2)依次取下一个元素向前依次比较
若小于前一元素,则交换位置,大于则位置不变
在这里插入图片描述

void insert() {
	for (int i = 0; i < max - 1; i++) {
		int end = i;
		int tem = a[end + 1];
		while (end >= 0) {
			if (tem < a[end]) {
			//将大值后移
				a[end + 1] = a[end--];//注意是end--
			} else
				break;
		}
		//end+1:因为前面if执行后end减一,固end+1,放tem
		a[end + 1] = tem;
	}
}

2、希尔排序

1) 选增量gap(gap=n/2,即将其分为2组)
2)分别对每组进行插入排序
3)重分gap(gap/=2,直至gap=1)在这里插入图片描述

void xier() {
	int n = max;
	while (n > 1) {
		n = n / 2;
		for (int i = 0; i < max - n; i++) {
			//直接插入排序
			int end = i;
			int tem = a[end + n];
			while (end >= 0) {
				if (tem < a[end]) {
					a[end + n] = a[end];
					end -= n;
				} else
					break;
			}
			a[end + n] = tem;
		}
	}
}

3、选择排序

1)找出数据中的最小值,将其与第一个值交换位置
2)继续找待排数据中的最小值,将其与第二个值交换位置
3)重复上述步骤,直至最后一个值
在这里插入图片描述

void swap(int *a, int *b) {
	int tem = *a;
	*a = *b;
	*b = tem;
}

void xuanze(int *arr) {
	int begin = 0, end = max - 1;
	while (begin < end) {
		int Min = begin, Max = begin;
		//找最大、最小值的下标
		for (int i = begin; i <= end; i++) {
			//找最小值下标
			if (arr[i] < arr[Min])
				Min = i;
			//找最大值下标
			if (arr[i] > arr[Max])
				Max = i;
		}
		//放最小值到前面
		swap(&arr[Min], &arr[begin]);
		//防止最大值在begin处被换走(巨关键@_@)
		if (begin == Max)
			Max = Min;
		//放最大值到后面
		swap(&arr[Max], &arr[end]);
		begin++;
		end--;
	}
}

4、冒泡排序

1)从前到后依次,两两比较
若前>后,交换两者位置
若前<后,用后继续向后比较在这里插入图片描述

void maopao() {
	int n = max;
	while (n--) {
		int flag = 0;
		for (int i = 1; i < max; i++) {
			if (a[i - 1] > a[i]) {
				swap(&a[i-1],&a[i]);
				flag = 1;
			}
			if (flag = 0)
				break;
		}
	}
}

5、快速排序(左右指针法)

(指针分别指向最左和最右)
1)选其中之一为分界值:key
2)左指针向右走,右指针向左走,并与key比较
若 右<key,则右指针将值赋给左指针,且左指针右移
若 右>key,则右指针左移
若 左<key,则左指针右移
若 左>key,则左指针将值赋给右指针,且右指针左移
(将小于key的放数组左边,大于的放右边)
3)当左右指针相遇时,让其等于key
4)左侧可再找一个key,继续重复上述步骤。右侧同理(递归)
在这里插入图片描述

void quick(int low, int high) {
	int i = low, j = high;
	if (i >= j)
		return;
	int tem = a[low];
	while (i != j) {
		while (a[j] >= tem && i < j)
			j--;
		while (a[i] <= tem && i < j)
			i++;
		if (i < j) {
			int x = a[i];
			a[i] = a[j];
			a[j] = x;
		}
	}
	int x = a[low];
	a[low] = a[i];
	a[i] = x;
	quick(low, i - 1);
	quick(i + 1, high);
}

6、堆排序

1)构建堆(类似于二叉排序树)(升序用大根堆,降序用小根堆

大根堆:每个节点的值都大于等于左右孩子节点
小根堆:每个节点的值都小于等于左右孩子节点

  • 从叶子节点开始向上比较
    若 大于根节点,则交换位置(反之则不变)

2)将堆顶与最后一个元素交换位置

  • 换后末尾元素不变,其他元素继续向上重构堆
//建立堆
//二叉树规律:找最后一节点的父节点:father=(len-1-1)/2
//固可得其左右子树(排最后的)L=father*2+1,R=father*2+1+1=len
void build(int *arr, int start, int end) {
	int temp = arr[start];
	for (int i = 2 * start + 1; i <= end; i = i * 2 + 1) {
		if (i < end && arr[i] < arr[i + 1])
			i++;
		if (arr[i] > temp) {
			arr[start] = arr[i];
			start = i;
		} else
			break;
	}
	arr[start] = temp;
}

//堆排序
void duipai(int *arr) {
	int len = max;
	for (int i = (len - 1 - 1) / 2; i >= 0; i--)
	//i:最后一个父节点
		build(arr, i, len - 1);
	int temp;
	//将栈顶放置末尾,即将最大值放置最后
	for (int i = 0; i < len - 1; i++) {
		swap(&arr[0],&arr[len-1-i]);
		//重构堆顶
		build(arr, 0, len - 1 - i - 1);
	}
}

在这里插入图片描述

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值