十大基础排序算法

一、冒泡排序
时间复杂度:O(n^2)
额外空间复杂度:O(1)

void swap(int arr[], int a, int b){
	int tmp = a;
	arr[a] = arr[b];
	arr[b] = tmp;
}
//首先判断数组是否需要排序
if(arr.size() < 2 || arr == null)
	return;
for(int end = arr.size()-1; end > 0; end--){
	for(int i = 0; i < end; i++){
		if(arr[i] > arr[i+1])
			swap(arr, i, i +1);
	}
}

二、插入排序
时间复杂度:O(n^2)
额外空间复杂度:O(1)

设数组有N个元素,则第一个元素一定自己有序;
把2到N位置的元素有序插到已经有序的数列上

void Insertion_sort(Element arr[], int N){
	if(N < 2)	return;
	for(int i = 1; i < N; i++){
		int tmp = arr[i];//待插入值
		for(int j = i; j > 0 && arr[j-1] > tmp; j--)//若待插入值的前一个元素大于自身,则前一个元素往后移一个位置
			arr[j] = arr[j-1];
		arr[j] = tmp;//待插入值最终位置
	}
}

三、选择排序
时间复杂度:O(n^2)
额外空间复杂度:O(1)

将未排序数组中最小值放到有序数列的最后

void swap(int arr[], int a, int b){
	int tmp = a;
	arr[a] = arr[b];
	arr[b] = tmp;
}
void Selection_sort(Element arr[], int N){
	for(int i = 0; i < N; i++){
		int minsub = i;
		for(int j = i+1; j < N; j++)
			minsub = arr[j] > arr[minsub] ? minsub : j;
		swap(arr, minsub, i);
	}
}

四、归并排序
时间复杂度O(N*logN);
额外空间复杂度O(N);

递归解法

void Merge(int A[], int tmpA[], int L, int R, int RightEnd){
	int LeftRight = L + (RightEnd - L) >> 1;
	int tmp = L, N = RightEnd - L + 1;
	while(L <= LeftEnd && R <= RightEnd){
		if(A[L] < A[R])	tmpA[tmp++] = A[L++];
		else	tmpA[tmp++] = A[R++];
	}
	while(L <= LeftEnd)	tmpA[tmp++] = A[L++];
	while(R <= RightEnd) tmpA[tmp++] = A[R++];
	for(int i = 0; i < N; i++)
		A[i] = tmpA[i];
}

void Msort(int A[], int tmpA[], int L, int RightEnd){
	int center;
	if(L < RightEnd){
		center = L + (Right - L) >> 1;
		Msort(int A[], int tmpA[], int L, int center);
		Msort(int A[], int tmpA[], int center+1, int RightEnd);
		Merge(int A[], int tmpA[], int L, int center+1, int RightEnd);
	}
}

void Merge_sort(int A[], int N){
	if(N < 2)	return;
	int *tmpA = malloc(N * sizeof(int));
	Msort(A, tmpA, 0, N-1);
	free(tmpA);
}

非递归解法(步长问题)

void mergesort(int A[], int N){
	for(int step = 2; step / 2 < N; step *= 2){
		for(int i = 1; i <= N; i += step){
			int mid = i + step/2 -1;
			if(mid <= N)
				Merge(A, i, mid, mid+1, min(i+step-1, n));
		}
	}
}

五、快速排序

int cutoff;
void Quicksort(Element A[], int L, int R){
	if(R-L < cutoff)//规模小就用别的排序
	{
		for(; ;){
			while(A[i++] < mid);	//mid是主元,取数组的头尾中的元素中位数
			while(A[j--] > mid);
			if(i < j)
				swap(A[i], A[]j);
			else//i > j就越界了
				break;
		}
		swap(A[i], A[R-1]);
		//此时,mid左边的元素都比mid小
		//以下递归实现
		Quicksort(A, L, i-1);
		Quicksort(A, i+1, R);
	}
	else	Insertsort(A, int R-L+1)
}

六、堆排序
借助完全二叉树思想,数组存储

//最大堆的建立
typedef struct HeapStruct *MaxHeap;
struct HeapStruct{
	ElementType *Elements;
	int size;
	int maxsize;
};
MaxHeap Creat(int N){
	MaxHeap H = malloc(sizeof(HeapStruct));
	H->Elements = malloc((N + 1) * sizeof(ElementType));
	H->maxsize = N;
	H->Elements[0] = MAX;//很大的值,比任何潜在的元素都大,哨兵
	return H;
}
//插入节点
void Insert(MaxHeap H, ElementType item){
	//判断最大堆是否已经满了
	int i;//i表示最大堆插入元素后 最后的位置
	if(H->size == H->maxsize)	return;
	i = ++H->size;
	//调整堆,使其变成最大堆,新插入的元素与父节点相比
	for(;H->Elements[i/2] < item; i /= 2)
		H->Elements[i] = H->Elements[i/2];
	H->Elements[i] = item;
}


//删除根节点(交换根节点和最后节点,然后调整堆)
ElementType DeleteMax(MaxHeap H){
	//判断是否为空
	if(H->size == 0)	return ;
	int parent, child, max = H->Elements[1];
	int temp = H->Elements[H->size];
	H->Elements[H->size--] = max;//把最大值放在数组最后
	//调整堆
	for(parent = 1; parent*2 <= H->size; parent = child){
		child = parent*2;//左孩子
		//找左右孩子中较大的那个
		if((child != H->size) && child < Elements[child+1])
			child++;
		if(temp >= H->Elements[child])	break;
		H->Elements[parent] = H->Elements[child];
	}
	H->Elements[parent] = temp;
}
//对上段代码进行size次循环即是堆排序

七、桶排序
普通版:
假设我们有N个学生,他们的成绩在0到100之间(于是又101个不同的成绩值)。
我们建立101个桶(容器)分别存放相同成绩的人;
比如

void Bucket_sort(ElementType arr[], int N){
	count[];//初始化
	while(每一个学生的成绩){
		将该学生插入到成绩所对应的桶中
	}
	for(int i = 0; i <= 100; i++)
		if(count[i])
			输出整个count[i]链表;
}

(一)计数排序
加入有一组待排序列,以及数据范围为[0, 200];
则我们建立长为200-0+1的整形数组,int count[201];
遍历所有数据,分别放到对应的桶中,然后顺序倒出;

while(cin >> num)
	count[num]++;
for(int i = 0; i < N; i++)
	if(count[i])
		cout << count[i];

上述排序,只适用于数据大小很集中的情况,类似0,1,2,999,10,5,6…等等就不适合了。
那我们该怎么办呢?看下面的基数排序;

升级版(二)基数排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值