数据结构排序合集(笔记)

目录

一.插入排序与希尔排序

二.选择排序与堆排序

三.冒泡排序和快速排序

四.归并排序

五.计数排序


一.插入排序与希尔排序

时间复杂度空间复杂度稳定性
插入排序O(N^2)O(1)稳定
希尔排序O(N^1.3)O(1)不稳定

插入排序: 

希尔排序(两个排序的时间复杂度是一样的,即使是四循环,他们效率也相同):


二.选择排序与堆排序

时间复杂度空间复杂度稳定性
选择排序O(N^2)O(1)不稳定
堆排序O(N*logN)O(1)不稳定

void SelectSort(int* a, int n)//选择排序
{
	int begin = 0;
	int end = n - 1;
	while(begin < end)
	{
		int mini = begin;
		int maxi = end;
		for (int i = begin; i <= end; i++)//选出最大和最小进行交换
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}
		swap(&a[mini], &a[begin]);
		if (begin == maxi)
			maxi = mini;
		swap(&a[maxi], &a[end]);
		end--;
		begin++;
	}
}

(选择排序是特别慢,也没有稳定性的排序,可能连冒泡都比不过)

堆排序( 因为要排升序,所以建大堆):


三.冒泡排序和快速排序

时间复杂度空间复杂度稳定性
冒泡排序O(N^2)O(1)稳定
快速排序O(N*logN)O(logN)~O(N)不稳定

冒泡排序:

快速排序:

int Getmid(int*a,int left,int right)//三数取中
{
	int midi = (left + right) / 2;
	if (a[right] > a[left])
	{
		if (a[midi] > a[right])
		{
			return right;
		}
		else if (a[midi] < a[left])
		{
			return left;
		}
		else
			return midi;
	}
	else// if (a[left] >= a[right])
	{
		if (a[midi] > a[left])
		{
			return left;
		}
		else if (a[midi] < a[right])
		{
			return right;
		}
		else
			return midi;
	}
}

不用使用递归的qsort(用堆去模拟递归)

void QuickSortNonR(int* a, int left, int right)
{
	Stack st;
	StackInit(&st);
	StackPush(&st, right);
	StackPush(&st, left);
	while (!StackEmpty(&st))
	{
		int begin = StackTop(&st);
		StackPop(&st);
		int end = StackTop(&st);
		StackPop(&st);

		int keyi = PartSort3(a, begin, end);
		if (keyi + 1 < end)
		{
			StackPush(&st, end);
			StackPush(&st, keyi + 1);
		}
		if (begin < keyi - 1)
		{
			StackPush(&st, keyi - 1);
			StackPush(&st, begin);
		}
	}
	StackDestroy(&st);
}

四.归并排序

时间复杂度空间复杂度稳定性
归并排序O(N*logN)O(logN)稳定

void _MergeSort(int* a, int* tmp, int left,int right)
{
	if (left >= right)
		return;
	int midi = (left + right) / 2;
	_MergeSort(a, tmp, left, midi);
	_MergeSort(a, tmp, midi+1, right);
	//归 
	int begin1 = left, end1 = midi;
	int begin2 = midi+1, end2 = right;
	int i = left;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] <= a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	memcpy(a+left, tmp+left, sizeof(int)*((right - left)+1));
}

非递归实现归并排序:

void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(n*sizeof(int));
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	int gap = 1;
	while (gap < n)
	{
		for (int i = 0; i < n;i += 2*gap)//
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			int j = i;
			//[i,end1] [i+gap,end2]

			if (begin2 >= n)
				break;
			if (end2 >= n)
				end2 = n-1;
			printf("[%d %d]  [%d %d]", begin1, end1, begin2, end2);
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] <= a[begin2])
				{
					tmp[j++] = a[begin1++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}
			}

			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}
			memcpy(a+i, tmp+i, sizeof(int) * (end2 - i +1));//
		}
		printf("\n");
		gap = 2*gap;
	}
	free(tmp);
	tmp = NULL;
}

五.计数排序

// 计数排序
void CountSort(int* a, int n)
{
	int max = a[0], min = a[0];
	for (int i = 0; i < n; i++)//选出最大最小得到区间大小
	{
		if (max < a[i])
			max = a[i];
		if (min > a[i])
			min = a[i];
	}

	int range = max - min +1 ;
	int* count = (int*)calloc(range,sizeof(int));
	if (count == NULL)
	{
		perror("malloc fail");
		return;
	}

	for (int i = 0; i < n; i++)//给新数组进行计数
	{
		count[a[i] - min]++;
	}
	int j = 0;
	for (int i = 0; i < range; i++)//覆盖旧数组
	{
		while (count[i]--)
		{
			a[j++] = i + min;
		}
	}
	free(count);
	count = NULL;
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供关于数据结构排序笔记。 内排序是指在排序过程中,所有待排序的数据元素全部存放在内存中进行排序。常见的内排序算法有冒泡排序、插入排序、选择排序、快速排序、归并排序等。 1. 冒泡排序 冒泡排序是一种交换排序。它的基本思想是:通过交换相邻两个元素的位置,把大的元素往后面移动,小的元素往前面移动,从而实现排序的目的。 代码实现: ```c void bubble_sort(int arr[], int len) { for (int i = 0; i < len - 1; i++) { for (int j = 0; j < len - i - 1; j++) { if (arr[j] > arr[j+1]) { swap(arr[j], arr[j+1]); } } } } ``` 2. 插入排序 插入排序是一种插入排序。它的基本思想是:将待排序的元素插入到已经排好序的序列中,从而得到一个新的、更大的有序序列。 代码实现: ```c void insertion_sort(int arr[], int len) { int i, j, tmp; for (i = 1; i < len; i++) { tmp = arr[i]; for (j = i; j > 0 && arr[j-1] > tmp; j--) { arr[j] = arr[j-1]; } arr[j] = tmp; } } ``` 3. 选择排序 选择排序是一种选择排序。它的基本思想是:每次从待排序的序列中选择一个最小的元素,放到已经排好序的序列的末尾,直到所有元素都排好序。 代码实现: ```c void selection_sort(int arr[], int len) { int i, j, min_idx; for (i = 0; i < len - 1; i++) { min_idx = i; for (j = i + 1; j < len; j++) { if (arr[j] < arr[min_idx]) { min_idx = j; } } swap(arr[i], arr[min_idx]); } } ``` 4. 快速排序 快速排序是一种分治排序。它的基本思想是:通过一趟排序将待排序序列分割成独立的两部分,其中一部分的所有元素都比另一部分的元素小,然后再对这两部分分别进行排序,直到整个序列排好序为止。 代码实现: ```c void quick_sort(int arr[], int l, int r) { if (l < r) { int i = l, j = r, x = arr[l]; while (i < j) { while (i < j && arr[j] >= x) j--; if (i < j) arr[i++] = arr[j]; while (i < j && arr[i] < x) i++; if (i < j) arr[j--] = arr[i]; } arr[i] = x; quick_sort(arr, l, i-1); quick_sort(arr, i+1, r); } } ``` 5. 归并排序 归并排序是一种分治排序。它的基本思想是:将待排序序列分成若干个子序列,每个子序列都是有序的,然后再将子序列合并成一个有序序列。 代码实现: ```c void merge(int arr[], int l, int m, int r) { int i, j, k; int n1 = m - l + 1; int n2 = r - m; int L[n1], R[n2]; for (i = 0; i < n1; i++) L[i] = arr[l + i]; for (j = 0; j < n2; j++) R[j] = arr[m + 1 + j]; i = 0; j = 0; k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k++] = L[i++]; } else { arr[k++] = R[j++]; } } while (i < n1) { arr[k++] = L[i++]; } while (j < n2) { arr[k++] = R[j++]; } } void merge_sort(int arr[], int l, int r) { if (l < r) { int m = (l + r) / 2; merge_sort(arr, l, m); merge_sort(arr, m+1, r); merge(arr, l, m, r); } } ``` 以上是内排序的几种常见算法。需要注意的是,不同的算法在不同的数据情况下,其效率也会有所不同。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值