排序算法。

冒泡排序两个两个看交换位置 每一轮都会有最大的泡泡找到他的位置 需要进行n轮 稳定

插入排序打扑克摸牌 顺序插入  摸n张牌 每次都得遍历 所以。。 稳定

最好情况按顺序来的  O(n)

选择排序 选出最小的放第一个位置(与第一个位置交换) 然后从第二个数开始判断再选出最小的放第一个位置

选出最小的2 然后2和3交换 两个3的相对位置变了 所以不稳定

快排 不稳定 最坏情况 每次选到最大的数作为标准 那么就得操作n层 

归并 稳定

快速排序:QuickSort

选标准值,将比标准值小的放在其左侧,将比标准值大的放在其右侧,左右两部分分别重复以上操作

1.挖坑填补法

拆东墙补西墙

先把第一个数拿出来用temp储存 然后从最后面遍历 找到比temp小的放到第一个位置 然后再从前面第二个开始遍历找比temp大的放在后面的空位上 重复操作 直到end和begin在一块 然后再在temp两边分别重复操作


 

#include<stdio.h>

int Find(int arr[],int nBegin,int nEnd)
{
	int temp = arr[nBegin];
	while(nBegin < nEnd)
	{
		//从后向前找比标准值小的
		while(nEnd > nBegin)
		{
			if(arr[nEnd] < temp)
			{
				arr[nBegin] = arr[nEnd];
				nBegin++;
				break;
			}
			nEnd--;			 
		}
		
		//从前往后找比标准值大的
		while(nBegin < nEnd)
		{
			if(arr[nBegin] > temp)
			{
				arr[nEnd] = arr[nBegin];
				nEnd--;
				break;
			}
			nBegin++;
		 } 
	}
	
	//标准值放入
	arr[nBegin] = temp;
	return nBegin; 
}

void QuickSort(int arr[],int nBegin,int nEnd)
{
	if(arr == NULL || nBegin >= nEnd)return;
	
	//确定标准值最终位置
	int nStandard;
	nStandard = Find(arr,nBegin,nEnd);
	
	//将数据分成两部分 分别重复以上操作
	QuickSort(arr,nBegin,nStandard-1);
	QuickSort(arr,nStandard+1,nEnd);
}

void Print(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;
	for(int i=0;i<length;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {2,4,7,1,5,14,89,13,2};
	QuickSort(arr,0,sizeof(arr)/sizeof(arr[0])-1);
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

 2.区间分割法

small指向begin-1 begin从前向后遍历 遇见比end小的 就交换small+1与begin 最终将小于10的全放在一边

若 a = i++; 则等价于 a=i;i=i+1; 而 a = ++i; 则等价于 i=i+1;a=i;

#include<stdio.h>


int Find(int arr[],int nBegin,int nEnd)
{
	int nSmall = nBegin-1;
	
	for(nBegin;nBegin < nEnd;nBegin++)
	{
		if(arr[nBegin] < arr[nEnd])
		{
			if(++nSmall != nBegin)
			{
				arr[nSmall] = arr[nSmall]^arr[nBegin];
				arr[nBegin] = arr[nSmall]^arr[nBegin];
				arr[nSmall] = arr[nSmall]^arr[nBegin];
			}
		}
	}
	
	//将标准值放入
	if(++nSmall != nEnd)
	{
		arr[nSmall] = arr[nSmall]^arr[nEnd];
		arr[nEnd] = arr[nSmall]^arr[nEnd];
		arr[nSmall] = arr[nSmall]^arr[nEnd];
	}
	return nSmall; 
}

void QuickSort(int arr[],int nBegin,int nEnd)
{
	if(arr == NULL || nBegin >= nEnd)return;
	
	//确定标准值最终位置
	int nStandard;
	nStandard = Find(arr,nBegin,nEnd);
	
	//将数据分成两部分 分别重复以上操作
	QuickSort(arr,nBegin,nStandard-1);
	QuickSort(arr,nStandard+1,nEnd);
}

void Print(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;
	for(int i=0;i<length;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {2,4,7,1,5,14,89,13,2};
	QuickSort(arr,0,sizeof(arr)/sizeof(arr[0])-1);
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
} 

快排的非递归

【数据结构与算法篇】手撕八大排序算法之快排的非递归实现及递归版本优化(三路划分)-阿里云开发者社区 (aliyun.com)

非递归实现 因为递归深度太深可能会导致栈溢出,可以使用栈来模拟递归

首先把整个数组的最右侧下标 也就是右区间入栈 再将左区间入栈 (因为取的时候就可以先取左区间,再取右区间,然后while循环栈不为空  每次取出一个左右区间 然后把整个左右区间放进Partition里面 他就会返回一个数组下标 下标左边的都比他小 下标右边的都比他大  这时候数组就被划分为两部分 再把这两部分 也就是四个下标放进栈中 然后循环下一轮 取出栈顶的一个区间再进行划分 直到区间大小为1 比如说【2,3】 就不用再划分了

void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
//hoare版本
int Partition1(int* a, int left, int right)
{
	int keyi = left;
	while (left < right)
	{
		//注意: 要加上left < right 否则会出现越界
		//若不判断等于基准值,也会出现死循环的情况
		//右边找小
		while (left < right && a[right] >= a[keyi])
		{
			right--;
		}
		//左边找大
		while (left < right && a[left] <= a[keyi])
		{
			left++;
		}
		Swap(&a[left], &a[right]);
	}
	Swap(&a[left], &a[keyi]);
	return left;
}
void QuicksortNonR(int* a, int begin, int end)
{
	Stack st;
	StackInit(&st);
	//注意栈的顺序是后进先出,需要倒着放进去,正着拿出来
	
	//将排序数组的起始和末端下标入栈
	StackPush(&st, end);
	StackPush(&st, begin);
	//栈不为空一直循环
	while (!StackEmpty(&st))
	{
		//弹出子区间(左右两个下标)
		int left = StackTop(&st);
		StackPop(&st);
		int right = StackTop(&st);
		StackPop(&st);
		//执行分区操作
		int keyi = Partition1(a, left, right);
		//[left,keyi - 1] keyi [keyi + 1, right]
		//注意只剩一个数或区间不存在则停止入栈
		if (keyi + 1 < right)
		{
			StackPush(&st,right);
			StackPush(&st,keyi + 1);
		}
		if (left < keyi - 1)
		{
			StackPush(&st, keyi - 1);
			StackPush(&st, left);
		}
	}
}
void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
}
int main()
{
	int a[] = { 9,6,7,1,4,5,5,2,10,1,6,3,7 };
	QuicksortNonR(a, 0, sizeof a / sizeof(int) - 1);
	PrintArray(a, sizeof a / sizeof(int));
}

MergeSort: 归并排序

将多个有序数组进行合并

排序算法:归并排序【图解+代码】_哔哩哔哩_bilibili

首先用递归的思想 分成各个小块 一半一半分

然后再两个两个合在一起

两个数组用两个指针比大小

小的放前面 

nlogn

稳定不稳定看你怎么写

小于等于稳定 小于是不稳定的

 

#include<stdio.h>
#include<stdlib.h>

void Merge(int arr[],int nBegin,int nEnd)
{
	int nBegin1 = nBegin;
	int nEnd1 = nBegin+(nEnd-nBegin)/2;
	int nBegin2 = nEnd1+1;
	int nEnd2 = nEnd;
	
	int *pTemp =NULL;
	pTemp = (int*)malloc(sizeof(int)*(nEnd-nBegin+1));
	int i=0;
	
	//遍历两个数组
	while(nBegin1 <= nEnd1 && nBegin2 <= nEnd2)
	{
		if(arr[nBegin2] < arr[nBegin1])
		{
			pTemp[i++] = arr[nBegin2++];
		}
		else
		{
			pTemp[i++] = arr[nBegin1++];
		}
	}
	
	//将有剩余的数组元素放置
	while(nBegin1 <= nEnd1)
	{
		pTemp[i++] = arr[nBegin1++];
	}
	while(nBegin2 <= nEnd2)
	{
		pTemp[i++] = arr[nBegin2++];
	}
	
	//放回
	for(int i=0;i<nEnd-nBegin+1;i++)
	{
		arr[nBegin+i] = pTemp[i];
	} 
	
	free(pTemp);
	pTemp = NULL; 	
} 


void MergeSort(int arr[],int nBegin,int nEnd)
{
	if(arr == NULL || nBegin >= nEnd)return;
	
	//分割 
	int nMid = nBegin + (nEnd-nBegin)/2;
	
	MergeSort(arr,nBegin,nMid);
	MergeSort(arr,nMid+1,nEnd);
	
	//合并
	Merge(arr,nBegin,nEnd); 
} 

void Print(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;
	for(int i=0;i<length;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {2,4,7,1,5,14,89,13,2};
	MergeSort(arr,0,sizeof(arr)/sizeof(arr[0])-1);
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
} 

冒泡排序:BubbleSort

相邻两个元素进行大小比较,如果前一个比后一个大,则二者发生交换

第一横:8和6比 8比6大 交换 8和3比 8比3大 交换 8和12比 没12大 不动 12和1比 比12大交换 12和7比 比12大交换 12没15大 不动

第二横;6和3比。。。。。。。

#include<stdio.h>

void BubbleSort(int arr[],int length)
{
	if(arr == NULL || length<=0)return;
	int i;
	int j;
	for(int i=0;i<length-1;i++)              //总排n-1回 
	{
		for(int j=0;j<length-i-1;j++)        //每次固定一个大的,然后俩俩比较再-1 
		{
			if(arr[j] > arr[j+1])
			{
				arr[j] = arr[j]^arr[j+1];
				arr[j+1] = arr[j]^arr[j+1];
				arr[j] = arr[j]^arr[j+1];
			}
		}
	}
}

void Print(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;
	for(int i=0;i<length;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {2,4,7,1,5,14,89,13,2};
	BubbleSort(arr,sizeof(arr)/sizeof(arr[0]));
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

堆排序:HeapSort

排序算法:堆排序【图解+代码】_哔哩哔哩_bilibili

#include<iostream>

using namespace std;
void print_arr(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        cout << " " << arr[i];
    }
	cout<<endl;
}
void swap(int * a, int * b) {
    int temp = * a;
    * a = * b;
    * b = temp;

}

/*
arr 存贮数组
n 数组长度
i 代维护节点下标
*/
void heapify(int arr[], int n, int i) {
    int largest = i;
    int lson = i * 2 + 1;
    int rson = i * 2 + 2;
    if (lson < n && arr[largest] < arr[lson])
        largest = lson;
    if (rson < n && arr[largest] < arr[rson])
        largest = rson;
    if (largest != i) {
        swap( & arr[largest], & arr[i]);
        heapify(arr, n, largest);
    }
}

//堆排序入口
void heap_sort(int arr[], int n) {
    //建堆
    for (int i = n / 2 - 1; i >= 0; i--) {
        heapify(arr, n, i);
    }
    //排序
    for (int i = n - 1; i >= 0; i--) {
        swap( & arr[i], & arr[0]);
        heapify(arr, i, 0);
    }
}
int main() {
	int arr[] = { 2,3,8,1,4,9,10,7,16,14 };
    int n = 10;
    print_arr(arr, n);
    heap_sort(arr, n);
    print_arr(arr, n);
    return 0;
}

首先先建立一个初始堆 从最后一个父节点开始建堆

具体的建堆逻辑是

largest最大节点下标

左节点下标 右节点下标

如果左节点比父亲节点大 就更新最大节点下标 右边同理

然后发现如果largest节点变了说明发生改动了 就应该交换 还需要进行递归操作 因为交换下来的节点也需要进行重复的判断

建堆完之后 头节点最大 需要交换头节点和最后一个节点 然后对头节点进行新一轮重复操作

桶排序:BucketSort

数据分组,各组之内进行排序

选择排序:SelectSort

找最大值放到最后/最小值放在最前面

6和3比3大 6和9比没九大 max=9的下标 9和1比 然后一顿比 最大放在最后

#include<stdio.h>

void SelectSort(int arr[],int length)
{
	if(arr == NULL || length<=0)return;
	int i;
	int j;
	
	int min;
	for(int i=0;i<length-1;i++)
	{
		min=i;
		for(int j=i+1;j<length;j++)
		{
			if(arr[j]<arr[min])
			{
				min=j;
			}
		}
		
		//最小值放入最前面
		if(min!= i)
		{
			arr[i]=arr[i]^arr[min];
			arr[min]=arr[i]^arr[min];
			arr[i]=arr[i]^arr[min];
		} 
	}
}

void Print(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;
	for(int i=0;i<length;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {2,4,7,1,5,14,89,13,2};
	SelectSort(arr,sizeof(arr)/sizeof(arr[0]));
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

插入排序:InsertSort

将待排序数据分成两部分,一部分有序,一部分无序,将无序元素依次插入到有序中去完成排序

#include<stdio.h>

void InsertSort(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;    //无序的第一个
	int j;    //有序的最后一个
	int temp;
	
	for(int i=1;i<length;i++)
	{
		j=i-1;
		temp=arr[i];  //无序的第一个元素
		while(j>=0 && temp<arr[j])
		{
			arr[j+1] = arr[j];
			j--;
		}
		arr[j+1]=temp; 
	} 
}

void Print(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;
	for(int i=0;i<length;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {2,4,7,1,5,14,89,13,2};
	InsertSort(arr,sizeof(arr)/sizeof(arr[0]));
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

希尔排序:ShellSort

将数据分组,各组之内插入排序,比原有插入排序更快,适合大量数据,不常用。

不稳定

 

计数排序:CountingSort

核心思想:基于非比较的排序

1.找最大值和最小值

2.计数

3.排序

#include<stdio.h>
#include<stdlib.h>
#include<string.h>   //memset

void CountingSort(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;
	int min = arr[0];
	int max = arr[0];
	
	//最大值最小值查找
	for(int i=1;i<length;i++)
	{
		if(arr[i]<min)
		{
			min=arr[i];
		}
		if(arr[i]>max)
		{
			max=arr[i];
		} 
	}
	
	//计数空间
	int *pCount=NULL;
	pCount=(int*)malloc(sizeof(int)*(max-min+1));
	memset(pCount,0,sizeof(int)*(max-min+1));
	
	//计数
	for(i=0;i<length;i++)
	{
		pCount[arr[i]-min]++;
	}
	
	//名次
	for(int i=1;i<max-min+1;i++)
	{
		pCount[i]=pCount[i]+pCount[i-1];
	}
	
	//排序
	int *pNew = (int*)malloc(sizeof(int)*length);
	for(i=length-1;i>=0;i--)
	{
		pNew[pCount[arr[i]-min]-1]=arr[i];
		pCount[arr[i]-min]--;
	}
	
	//放回原数组
	for(int i=0;i<length;i++)
	{
		arr[i]=pNew[i];
	}
	
	free(pNew);
	pNew=NULL;
	free(pCount);
	pCount=NULL; 
}
void Print(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;
	for(int i=0;i<length;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {2,4,7,1,5,14,89,13,2};
	CountingSort(arr,sizeof(arr)/sizeof(arr[0]));
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
}

基数排序:RadixSort

LSD:低位优先

MSD:高位优先

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct node
{
	int value;
	struct node *pNext;
}Radix;

void RadixSort(int arr[],int length)
{
	if(arr == NULL || length <= 0)return;
	
	//找最大值
	int nMax = arr[0];
	int i;
	for(int i=1;i<length;i++) 
	{
		if(arr[i] > nMax)
		{
			nMax = arr[i];
		}
	}
	
	//计算最大值位数
	int nCount = 0;
	while(nMax)
	{
		nMax/=10;
		nCount++;
	}
	
	//按位处理
	int nLoopTimes;
	int nbase = 1;
	
	//表头 
	Radix **pRadix = NULL;
	pRadix = (Radix**)malloc(sizeof(Radix*)*10);
	memset(pRadix,0,sizeof(Radix*)*10);
	
	for(nLoopTimes = 1;nLoopTimes<=nCount;nLoopTimes++)
	{
		i = nLoopTimes;
		while(i>1)
		{
			nbase*=10;
			i--;
		}
		
		//数据入组
		Radix *pTemp = NULL;
		for(i = 0;i<length;i++)
		{
			pTemp = (Radix*)malloc(sizeof(Radix));
			pTemp->value = arr[i];
			pTemp->pNext = NULL;
			
			//尾添加
			if(pRadix[arr[i]/nbase%10] == NULL)
			{
				pRadix[arr[i]/nbase%10] = pTemp;
			}
			else
			{
				Radix *pNode = pRadix[arr[i]/nbase%10];
				
				while(pNode->pNext)
				{
					pNode = pNode->pNext;
				}
				pNode->pNext = pTemp;
			}
		}
		
		//放回 
		int j=0;
		for(i=0;i<10;i++)
		{
			pTemp = pRadix[i];
			while(pTemp)
			{
				arr[j]=pTemp->value;
				pTemp = pTemp->pNext;
				j++;
			}
		} 
		
		//释放
		Radix *pDel = NULL;
		for(int i=0;i<10;i++)
		{
			pTemp = pRadix[i];
			while(pTemp)
			{
				pDel = pTemp;
				pTemp = pTemp->pNext;
				free(pDel);
				pDel = NULL;
			}
		}
		//清空
		memset(pRadix,0,sizeof(Radix*)*10); 	 
	} 
	free(pRadix);
	pRadix = NULL;
}

void Print(int arr[],int length)
{
	if(arr == NULL || length <=0)return;
	
	int i;
	for(int i=0;i<length;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = {53, 3, 542, 748, 14, 214, 154, 63, 616};
	RadixSort(arr,sizeof(arr)/sizeof(arr[0]));
	Print(arr,sizeof(arr)/sizeof(arr[0]));
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值