排序大荟萃

发布时间:2020-06-28 17:15:29 作者:momo462
来源:网络 阅读:405






选择排序的基本思想:从待排序序列中找到最小(大)的元素,存放到序列起始位置,缩小排序范围,再找当前序列最小(大)的元素,放在起始位置之后,直到所有数据都被排完。

时间复杂度=O(n^2)

空间复杂度=O(1)

最好情况:已经有序 交换次数O(1)

最坏情况:逆序 交换次数O(n-1)

下面是c++版本的代码实现

#include <iostream>
using namespace std;
//初始版本,每次找到最小的
void SelectSort(int *a,size_t size)
{
    //比较次数:n*(n-1)/2
    for(size_t i=0;i<size;i++)
    {
        
        int min=i;
        for(size_t j=i+1;j<size;j++)
        {
            //交换次数:0~n-1之间
            if(a[min]>a[j])
            {
                min=j;
            }
        }
        //赋值次数:0~3(n-1)之间
        if(min!=i)
        {
             swap(a[min],a[i]);
        }
        
    }
}

//改进版本,每次确定最大的和最小的
void SelectSort(int *a,size_t size)
{
    //1/2数列的长度
    for(size_t left=0,right=size-1;left<right;left++,right--)
    {
        int min=left;
        int max=right;
        for(size_t j=left+1;j<=right;j++)
        {
            if(a[min]>a[j])
            {
                min=j;
            }
            if(a[max]<a[j])
            {
                max=j;
            }
        }
        if(min!=left)
		{
		        //极端情况 左边最大 右边最小
			if(min==right&&max==left)
			{
				swap(a[min],a[left]);
			}
			//左边的最大 先将左边的移过去
			else if(min!=right&&max==left)
			{
				swap(a[max],a[right]);
				swap(a[min],a[left]);
			}
			else
			{
				swap(a[min],a[left]);
			}
		}
		if(max!=right)
		{
			swap(a[max],a[right]);
		}
    }
}
#include <iostream>
using namespace std;
//建局部堆----向下调整
void AdjustDown(int *a,int  size,int index)
{
    parent=index;
    int child=parent*2+1;
    while(child<size)
    {
        //如果a[child+1]存在,找a[child+1]和a[child]中的最大值
        if(child+1<size&&a[child+1]>a[child])
        {
            child++;
        }
        //如果孩子结点大于父结点,交换,并且看交换完之后,这个局部是否还满足条件
        if(a[child]>a[parent])
        {
            swap(a[child],a[parent]);
            parent=child;
            child=parent*2=1;    
        }
        //如果孩子结点不大于父节点,可以直接跳出
        else
        {
            break;
        }
    }
}
//堆排序
void HeapSort(int *a,int size)
{
    //将数组转化成堆----O(logn)
    for(int i=(size-2)/2;i>=0;i--)
    {
        AdjustDown(a,size,i);
    }
    //O(nlogn)
    for(int i=0;i<size;i++)
    {
        //交换堆顶和最后一个结点
        swap(a[size-1-i],a[0]);
        //堆得范围减小,并且建堆
        AdustDown(a,size-i-1,0);
    }
}
#include <iostream>
using namespace std;
//直接插入排序
void InsertSort(int *a,size_t size)
{
  for(size_t i=1;i<size;i++)
  {
      int end=i-1;
      int temp=a[i];
      while(end>=0&&a[end]>temp)
      {
          a[end+1]=a[end];
          end--;
      }
      //当end所在位置的数比temp小时,while跳出循环,end指向带插入位置的前一个位置
      //所以end+1,才是temp该放的位置
      a[end+1]=temp;   
  }   
}
#include <iostream>
using namespace std;
void ShellSort(int *a,int size)
{
    //增量值得设定
    int gap=size;
    while (gap>1)
	{
		gap=gap/3+1; 
		for (size_t i=gap;i<size;i++)
		{
			int index=i;
			int end=index-gap;
			int temp=a[index];
			while (end>=0&&temp<a[end])
			{
				a[end+gap]=a[end];
				end-=gap;
			}
			a[end+gap]=temp;
		}
	}
}
//合并
void GetMerge(int *a,int begin1,int end1,int begin2,int end2,int *temp)
{
	int i=0;
	while(begin1<=end1&&begin2<=end2)
	{
		if (a[begin1]<a[begin2])
		{
			temp[i++]=a[begin1];
			begin1++;
		}
		else
		{
			temp[i++]=a[begin2];
			begin2++;
		}
	}
	while(begin1<=end1)
	{
		temp[i++]=a[begin1++];
	}
	while(begin2<=end2)
	{
		temp[i++]=a[begin2++];
	}
}
//分解
void _MergeSort(int *a,int left,int right)
{
	if (right-left<1)
	{
		return;
	}
	int mid=left+(right-left)/2;
	_MergeSort(a,left,mid);
	_MergeSort(a,mid+1,right);
	int *temp=new int[right-left+1];
	GetMerge(a,left,mid,mid+1,right,temp);
	memcpy(a+left,temp,(right-left+1)*sizeof(int));

}
//归并排序
void MergeSort(int *a,size_t size)
{
	_MergeSort(a,0,size-1);
}
void Print(int *a,size_t size)
{
	for (size_t i=0;i<size;i++)
	{
		cout<<a[i]<<" ";
	}
	cout<<endl;

}


//归并排序的非递归写法
void MergeSortNor(int *a,size_t size)
{
	//先分成一个一个的然后两两排序合并
	int temp[10];
	size_t begin=0;
	size_t gap=0;
	size_t end=begin+gap+1;
	for (gap;gap<size;gap+=begin-end)
	{
		for(begin=0;begin<size;begin+=gap*2+2)//如果有个是单着的???
		{
			end=begin+gap+1;
			if(begin+gap<size&&end<size&&end+gap<size)
			{
				GetMerge(a,begin,begin+gap,end,end+gap,temp+begin);
			}
			else
			{
				if(begin+gap<size)
				{
					if (end<size)
					{
						GetMerge(a,begin,begin+gap,end,size-1,temp+begin);
					}
					else
						//[8,9][9,9]----数组越界
						//[8,9][10,9]
						GetMerge(a,begin,begin+gap,size,size-1,temp+begin);
				}
				else
				{
					//[8,9][9,9]
					//[8,9][10,9]
					GetMerge(a,begin,size-1,size,size-1,temp+begin);
				}
			}
		}
		memcpy(a,temp,sizeof(int)*size);
	}
	
}

算法思想:

  1. 冒泡排序算法的运作如下:(从后往前)

  2. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。

  3. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

  4. 针对所有的元素重复以上的步骤,除了最后一个。

  5. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

优点:稳定性算法

缺点:时间复杂度高

时间复杂度:O(N^2)(平均时间复杂度)

空间复杂度:O(1)

以下是c++代码

void BubbleSort(int *a1,size_t size)
{
	for (size_t i=0;i<size;i++)
	{
		for (size_t j=0;j<size-i-1;j++)
		{
			if (a[j]>a[j+1])
			{
				swap(a[j],a[j+1]);
			}
		}
	}
}

快速排序是对冒泡排序的一种改进。

它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。其中作为分隔数据的关键数据我们成为Key,当key为当前数列中的最大值时,快速排序就是冒泡排序.

最好情况:O(nlogn)

最坏情况:O(n^2)

时间复杂度:O(nlogn)

空间复杂度:O(1)

排序大荟萃

C++代码实现

(1)基础版---选择数列的最后一个数作为key,递归快排

//单趟排序
int PartionSort(int *a1,int left,int right)
{
	int begin=left;
	int end=right-1;
	int key=a[right];
	while(begin<end)
	{
		while(begin<end&&a[begin]<key)
		{
			begin++;
		}
		while(end>begin&&a[end]>key)
		{
			end--;
		}
		if (end!=begin)
		{
			swap(a[end],a[begin]);
			end--;
			begin++;
		}
	}
	if (a[begin]>key)
	{
		swap(a[begin],a[right]);
		return begin;
	}
	else
	{
		return begin;
	}
}
//快速排序--递归思想
void QuickSort(int *a1,int left,int right)
{
	assert(a);
	if (left<right)
	{
		int boundary=PartionSort(a,left,right);
		QuickSort(a,left,boundary-1);
		QuickSort(a,boundary+1,right);
	}
}

(2)改进版:选择key值时,用三数取中,避免最坏情况的发生。

//单趟排序
int PartionSort(int *a1,int left,int right)
{
	int begin=left;
	int end=right-1;
	int key=a[right];
	while(begin<end)
	{
		while(begin<end&&a[begin]<key)
		{
			begin++;
		}
		while(end>begin&&a[end]>key)
		{
			end--;
		}
		if (end!=begin)
		{
			swap(a[end],a[begin]);
		}
	}
	if (a[begin]>key)
	{
		swap(a[begin],a[right]);
		return begin;
	}
	else
	{
		return right;
	}
}

//快速排序---三数取中
void QuickSort(int *a1,int left,int right)
{
	assert(a);
	int mid=left+(right-left)/2;
	if (left<right)
	{
		if (a[left]<a[right])
		{
			if (a[right]<a[mid])
			{
				swap(a[mid],a[right]);
			}
			if (a[left]>a[mid])
			{
				swap(a[mid],a[left]);
			}
		}
		else
		{
			if (a[left]<a[mid])
			{
				swap(a[mid],a[left]);
			}
			if (a[right]>a[mid])
			{
				swap(a[mid],a[right]);
			}
		}
		swap(a[mid],a[right]);
		int boundary=PartionSort(a,left,right);
		QuickSort(a,left,boundary-1);
		QuickSort(a,boundary+1,right);
	}
}

(3)对每次排序进行优化,当数列中个数小于13(STL中这样实现的),应用插入排序。

//单趟排序
int PartionSort(int *a1,int left,int right)
{
	int begin=left;
	int end=right-1;
	int key=a[right];
	while(begin<end)
	{
		while(begin<end&&a[begin]<key)
		{
			begin++;
		}
		while(end>begin&&a[end]>key)
		{
			end--;
		}
		if (end!=begin)
		{
			swap(a[end],a[begin]);
		}
	}
	if (a[begin]>key)
	{
		swap(a[begin],a[right]);
		return begin;
	}
	else
	{
		return right;
	}
}
//快速排序中个数少时用插入排序
void QuickSort(int *a1,int left,int right)
{
	assert(a);
	if(right-left<13)
	{
		InsertSort(a,right-left+1);
	}
	if (left<right)
	{
		int boundary=PartionSort(a,left,right);
		QuickSort(a,left,boundary-1);
		QuickSort(a,boundary+1,right);
	}
}

(4)快排的非递归版本(栈实现)

//快速排序非递归实现
//手动利用栈来存储每次分块快排的起始点,栈非空时循环获取中轴入栈。
void QuickSort(int *a1,int left,int right)
{
	stack<int> s1;
	if(left<right)
	{
		int boundary=PartionSort(a,left,right);
		if (boundary-1-left>1)
		{
			s1.push(left);
			s1.push(boundary-1);
		}
		if (right-(boundary+1)>1)
		{
			s1.push(boundary+1);
			s1.push(right);
		}
		while (!s1.empty())
		{
			int r=s1.top();
			s1.pop();
			int l=s1.top();
			s1.pop();
			boundary=PartionSort(a,l,r);
			if (boundary-1-l>1)
			{
				s1.push(l);
				s1.push(boundary-1);
			}
			if (r-(boundary+1)>1)
			{
				s1.push(boundary+1);
				s1.push(r);
			}
		}
	}
}

(5)模拟单链表中的快排

int PartionSortLink(int *a1,int left,int right)
{
	int prev=left-1;
	int cur=left;
	int key=a[right];
	while(cur<right)
	{
		if (a[cur]<key)
		{

			prev++;
			if (prev!=cur)
			{
				swap(a[prev],a[cur]);
			}
		}
		if (cur==right-1)
		{
			prev++;
			swap(a[prev],a[right]);

		}
		cur++;
	}
	return prev;
}
void QuickSortLink(int *a1,int left,int right)
{
	assert(a);
	if (left<right)
	{
		int boundary=PartionSortLink(a,left,right);
		QuickSortLink(a,left,boundary-1);
		QuickSortLink(a,boundary+1,right);
	}
}


推荐阅读:
  1. 极客Web前端开发资源大荟萃#016
  2. 极客Web前端开发资源大荟萃#007

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

堆排序 快速排序 选择排序

上一篇:两组raid5两块盘掉线数据恢复成功案例-有方案

下一篇:C#字段和属性的使用说明

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》