排序方法总结

一.直接插入排序

思想:把数组0下表作为哨兵位,之后的没考虑一位放入哨兵位的值与之前的值进行比较,大于则不进行操作;小于的话,依次向后移动(采用直接赋值的方法),直到找到插入的位置,替换值即可。

时间复杂度为O(n^2),属于简单排序。

方法一:

#include<iostream>
using namespace std;
/*直接插入排序*/

void InsertSort(int ar[],int n)
{
	int j;
	for (int i = 2; i < n; ++i)//从第三位开始遍历
	{
		if (ar[i] < ar[i- 1] )//如果小于前面一位则进行操作
		{
			ar[0] = ar[i];//将小于前面的值放入哨兵位
			ar[i] = ar[i - 1];//再把前面一位覆盖到后面
			for (j= i - 1; ar[0] < ar[j - 1]; --j)//寻找放入的位置
				ar[j] = ar[j - 1];//数据整体后移,直到哨兵位大于ar[j-1]
			ar[j] =ar[0] ;
		}
	}
	for (int i = 1; i<n; i++)
		cout << ar[i] << " ";
	cout << endl;
}
int main()
{
	int ar[] = { 0,13,4,34,56,23,16,72,64,79,14,25 };
	int n = sizeof(ar) / sizeof(int);
	InsertSort(ar, n);
	
	return 0;
}

方法二: 

//直接插入排序:将第一个数据看做一个顺序表,将后面的数据一次插入表中  
void InsertSort(int a[], int n)    
{    
    for(int i= 1; i<n; i++){    
        if(a[i] < a[i-1]){               //若第i个元素大于i-1元素,直接插入。小于的话,移动有序表后插入    
            int j= i-1;   //表中最后一个数据  
            int x = a[i];        //复制为哨兵,即存储待排序元素    
            a[i] = a[i-1];           //先后移一个元素 (因为a[i]就是X,所以不怕丢失)   
            while(j>=0 && x < a[j]){  //查找在有序表的插入位置  (遍历表)  
                a[j+1] = a[j];    
                j--;         //元素后移    
            }    
            a[j+1] = x;      //插入到正确位置    
        }    
    }    
        
}   
int main()  
{  
    int n;  
    cin>>n;  
    int *a=new int[n];  
    for(int j=0;j<n;j++)  
        cin>>a[j];  
    InsertSort(a,n);  
    for(int i=0;i<n;i++)  
        cout<<a[i];  
    delete []a;  
}

2.堆排序

//堆排序:树形选择排序,将带排序记录看成完整的二叉树,第一步:建立初堆,第二步:调整堆  
//第二步:调整堆  
void HeapAdjust(int a[],int s,int n)  
{  
    //调整为小根堆,从小到大  
    int rc=a[s];  
    for(int j=2*s;j<=n;j*=2)  
    {  
        if(j<n && a[j]>a[j+1])//判断左右子数大小  
            j++;  
        if(rc<=a[j])  
            break;  
        a[s]=a[j];  
        s=j;  
    }  
    a[s]=rc;  
}  
//第一步:建初堆  
void CreatHeap(int a[],int n)  
{  
    //小根堆  
    for(int i=n/2;i>0;i--)  
        HeapAdjust(a,i,n);  
}  
//整合  
void HeapSort(int a[],int n)  
{  
    CreatHeap(a,n);//第一步,建立初堆  
    for(int i=n;i>1;i--)  
    {  
        int x=a[1];//堆顶与最后一个元素互换  
        a[1]=a[i];  
        a[i]=x;  
        HeapAdjust(a,1,i-1);  
    }  
  
}  
int main()  
{  
    int n;  
    cin>>n;  
    int *a=new int[n+1];  
    for(int j=1;j<n;j++)//注意:这里是从1开始的  
        cin>>a[j];  
    HeapSort(a,n);  
    for(int i=1;i<n;i++)  
        cout<<a[i];  
    delete []a;  
}  

3.选择排序

//简单选择排序:遍历一次找到最小与第一个元素呼唤位置,再从第二个元素开始遍历找到最小与第二个元素呼唤位置...  
void SelectSort(int a[],int n)  
{  
    for(int i=0;i<n-1;i++)  
    {  
        int k=i;//记录最小的那个下标的  
        for(int j=i+1;j<n;j++)  
            if(a[j]<a[k])  
                k=j;  
        if(k!=i)  
        {  
            int t=a[i];  
            a[i]=a[k];  
            a[k]=t;  
        }  
  
    }  
}  
int main()  
{  
    int n;  
    cin>>n;  
    int *a=new int[n];  
    for(int j=0;j<n;j++)  
        cin>>a[j];  
    SelectSort(a,n);  
    for(int i=0;i<n;i++)  
        cout<<a[i];  
    delete []a;  
} 

4.快速排序

       也叫分区排序,是目前应用最广泛的排序算法。实际上标准C++类库中的排序程序就被称为qsort,
排序算法是其实现中最基本的算法。
思想:任取待排序元素序列中的某个元素作为基准,按照该元素的排序码大小,将整个元素序列划分为
左右两个子序列:左侧子序列中所有元素的排序码都小于基准元素的排序码,右侧子序列中所有元素的排序
码都大于或等于基准元素的排序码,基准元素则排序在这两个子序列中间(这也是该元素最终应安放的位置)。
然后分别对这两个子序列重复施行上述方法,直到所有元素都排在相应位置上位置。
平均时间复杂度:O(nlog以2为底n)

int Partition(int Vector[], const int low, const int high)
{
	int pivotpos = low,pivot = Vector[low];//定义出基准元素
	for (int i = low + 1; i <= high; i++)//检测整个序列并进行划分
	{
		if (Vector[i] < pivot)
		{
			pivotpos++;
			if (pivotpos != i)
				swap(Vector[pivotpos], Vector[i]);//小于基准元素的交换到左侧去
		}
	}
	Vector[low] = Vector[pivotpos];
		Vector[pivotpos] = pivot;//将基准元素重新定位
		return pivotpos;//返回基准元素
}
void QuickSort(int a[],const int left ,const int right) //采用递归实现
{
	if (left < right)//当元素的序列大于1时候
	{
		int pivotpos = Partition(a, left, right);//进行划分
		QuickSort(a, left, pivotpos - 1);//对左侧的子序列进行处理
		QuickSort(a, pivotpos + 1, right);//对右侧的子序列进行处理
	}//元素序列长度小于等于1时候不处理
}

改进算法:快速-直接插入混合排序算法
思想:虽然快速排序是一个效率很高的排序算法,但是对于长度很小的序列,快速
排序算法的速度并不比一些简单排序算法快,研究表明M取值5~25时候,采用直接插
入排序排序至少快10%。在快速排序算法的递归实现中程序多次因为小的子序列而调
用自身因此快速排序算法进行改进的一个简单方法:就是在递归调用过程,当待排序
的序列规模小于预先确定的M时候,程序调用直接插入排序算法对此子序列进行排序。
 

#define M 5
void QuickSort(int l[], const int left, const int right)
{
	if (right - left <= M)return;
	int pivotpos = Partition(l, left, right);
	QuickSort(l, left, pivotpos - 1);
	QuickSort(l, pivotpos + 1, right);
}
void InsertSort(int L[], const int left, const int right)
{
	int temp, i, j;
	for (i = left + 1; i < right; i++)
	{
		if (L[i] < L[i - 1])
		{
			temp = L[i];
			j = i - 1;
			do
			{
				L[j + 1] = L[j]; 
				j--;
			} while (j>left&&temp<L[j]);
			L[j + 1] = temp;
		}
	}
}
void HybridSort(int L[], const int left, const int right)
{
	QuickSort(L, left, right);
	InsertSort(L, left, right);
}

5.冒泡排序

//传统冒泡排序  
void maopao(int a[],int n)  
{  
    for(int i=0;i<n-1;i++)  
        for(int j=0;j<n-i-1;j++)  
            if(a[j]>a[j+1])  
            {  
                int t=a[j];  
                a[j]=a[j+1];  
                a[j+1]=t;  
            }  
}  
int main()  
{  
    int n;  
    cin>>n;  
    int *a=new int[n];  
    for(int j=0;j<n;j++)  
        cin>>a[j];  
    maopao(a,n);  
    for(int i=0;i<n;i++)  
        cout<<a[i];  
    delete []a;  
}  

6.希尔排序

思想:设待排序元素序列有n个元素,首先取一个整数gap<n作为间隔,将全部元素分为gap个子序列。然后缩小间隔gap,直到最后取gap==1,将所有元素放在同一个序列排序为止。

void Shellsort(int a[], const int left, const int right)
{
	int i, j, gap = right - left + 1;//增量的初始化
	int temp;
	do {
		gap = gap / 3 + 1;//求下一增量值
		for (i = left / gap; i <= right; i++)//各子序列交替处理
		{
			if (a[i] < a[i - gap])//逆序
			{
				temp = a[i];
				j = i - gap;
				do {
					a[j + gap] = a[j];//后移元素
					j = j - gap;//再比较前一个元素
				} while (j > left&&temp < a[j]);
				a[j + gap] = temp;
			}
		}
	}while(gap > 1);
}
void shell_sort(int array[], int length) {
	int i;
	int j;
	int k;
	int gap;	//gap是分组的步长
	int temp;	//希尔排序是在直接插入排序的基础上实现的,所以仍然需要哨兵
	for (gap = length / 2; gap>0; gap = gap / 2) 
	{
		for (i = 0; i<gap; i++)
		{
			for (j = i + gap; j<length; j = j + gap)
			{	//单独一次的插入排序
				if (array[j] < array[j - gap]) 
				{
					temp = array[j];	//哨兵
					k = j - gap;
					while (k >= 0 && array[k]>temp) 
					{
						array[k + gap] = array[k];
						k = k - gap;
					}
					array[k + gap] = temp;
				}
			}
		}
	}
}

7.基数排序

也称多关键字排序 分发与回收  
基数:关键值的大小 多关键字取决于基数的多少
比如:3位长的数先按照个位把整个数放在对应的下表链表中排序,然后依次回收到数组。 同理十位,百位依次进行,最终数组中的数就排好序了

#include<iostream>
using namespace std;
#include<list>
list<int> lst[10];
void Distribute(int ar[], int n, int k)
{
	int tmp;
	int x;
	for (int i = 0; i < n; i++)
	{
		x = k;
		tmp = ar[i];
		while (tmp&&x > 0)
		{
			tmp /= 10;
			x--;
		}
		lst[tmp % 10].push_back(ar[i]);
	}
}

void Collect(int ar[])
{
	int k = 0;
	for (int i = 0; i < 10; i++)
	{
		while (!lst[i].empty())
		{
			ar[k++] = lst[i].front();
			lst[i].pop_front();
		}
	}
}
void RadixSort(int ar[], int n)
{
	for (int i = 0; i < 3; i++) 
	//循环三次第一次从个位放入链表,第二次从十位位,第三次从百位
	{
		Distribute(ar, n, i);
		Collect(ar);
	}
}
int main()
{
	
	int ar[] = { 278, 109, 63, 930, 589, 184, 505, 269, 8, 83 };
	int n = sizeof(ar) / sizeof(int);
	RadixSort(ar, n);

	for (int i = 0; i<n; ++i)
		cout << ar[i] << " ";
	cout << endl;
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值