排序算法

<span style="font-size:14px;">/*
 冒泡排序
 算法:
 核心思想是扫描数据清单,寻找出现乱序的两个相邻的项目。当找到这两个项目后
 交换项目的位置然后继续扫描。重复上面的操作直到所有的项目都按顺序排好
 时间复杂度n*n  (n-1)*n/2
 */
void BubblueSortDate(int SortDate[] , int Length)
{
	int tempDate = 0;
	bool swapFlag = true;
	for(int i = 0; i < Length - 1 && swapFlag; i++)
	{
		swapFlag = false;
		for(int j = 0; j < Length - i - 1; j++)
		{
			if(SortDate[j] > SortDate[j+1])
			{
				tempDate = SortDate[j];
				SortDate[j] = SortDate[j+1];
				SortDate[j+1] = tempDate;
				swapFlag = true;
			}
		}
		if(!swapFlag)
		return ;
	}

}

void SortPrint(int SortPrintf[] , int Length )
{
	for(int i=0; i<Length; i++)
	{
		cout<<SortPrintf[i]<<" ";
	}
}

 /*
 快速排序是对起泡排序的一种改进,通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键
 字小,则可分别对这两部分继续进行排序,以达到整个序列有序.
 交换顺序表L中子表L.r[low..high]的记录,使枢轴记录到位,并返回其所在位置,此时在它之前(后)的记录均不大(小)于它
 时间复杂度为 n*logn,其平均性能最好,若初始记录序列按关键字有序或基本有序,快速排序将锐化为起泡排序
 */
int  Partition(int SortData[], int low, int high)
{
     int tmpData = SortData[low];//用于子表的第一个记录作枢轴记录
     int temp=0;
 
     while ( low<high )
     {
         //从表的两端交替的向中间扫描
         while (low<high && SortData[high]>=tmpData)
         {
             high--;
         }
         //将比枢轴记录小的记录移到低端
         SortData[low] =SortData[high];
 
         while (low<high && SortData[low]<=tmpData)
         {
             low++;
         }
         //将比枢轴记录大的记录移到高端
         SortData[high] =SortData[low];
     }
     //枢轴记录到位
     SortData[low] =tmpData;
 
     return low;//返回枢轴所在位置
 }
 
 void QuickSortData(int SortData[], int low, int high)
 {
     int offset;
 
     if ( low<high )
     {
         offset = Partition(SortData, low, high);
         QuickSortData(SortData, low, offset-1);
         QuickSortData(SortData, offset+1, high);
     }
 }

//快速排序
void QuickSort(int data[],int low , int high)
{
	 int i, j, prvotkey;
	 if(low < high)
	 {
		  prvotkey = data[low];//以数组的第一个元素作为基本元素进行划分
		  i = low;
		  j = high;
		  while(i<j)//从数组两端交替的向中间扫描
		  {
			   while(i<j && data[j]>=prvotkey)
			   {
					j--;
			   }
			   if(i < j)
					data[i++] = data[j];//比基准元素小的移到低下标段

			   while(i<j && data[i]<=prvotkey)
			   {
					i++;
			   }
			   if(i < j)
					data[j--] = data[i];//比基准元素大的移到高下标段
		  }
		 
		  data[i] = prvotkey;  //移动基准元素到正确位置
		  QuickSort(data , low , i-1);//对前半个子表递归排序
		  QuickSort(data , i+1 , high);//对后半个子表递归排序
	 }

 }



/*
 直接插入排序
 算法:经过i-1遍处理后,L[1..i-1]己排好序。第i遍处理仅将L[i]插入L[1..i-1]的适当位置,
 使得L[1..i]又是排好序的序列。要达到这个目的,我们可以用顺序比较的方法。
 首先比较L[i]和L[i-1],如果L[i-1]<=L[i],则L[1..i]已排好序,第i遍处理就结束了;
 否则交换L[i]与L[i-1]的位置,继续比较L[i-1]和L[i-2],直到找到某一个位置j(1≤j≤i-1),
 使得L[j] ≤L[j+1]时为止
 优点:移动元素次数少,只需要一个辅助空间
 时间复杂度n*n
 当待排序记录的数量n很小时,这是一种很好的排序方法。但是n很大时,则不适合
 */
void InsertSortData(int SortData[], int Length)
 {
     int tmpData =0;
     int i=0;
     int j=0;
 
     for(i=1; i<Length; i++)
     {
         if ( SortData[i] <SortData[i-1])
         {
             tmpData =SortData[i];
             //数据往后移动
             for (j=i-1; j>=0 && tmpData<SortData[j]; j--)
             {
                 SortData[j+1] =SortData[j];
             }
             //将数据插入到j+1位置
             SortData[j+1] =tmpData;
         }
     }
     return;
 }

 /*
 拆半插入排序所需要的辅助空间和直接插入排序相同,从时间上比较,折半插入排序仅减少了关键字间的比较次数,而记录的移动次数不变。
 因为时间复杂度仍为n*n
 */
 void BInsertSortData(int SortData[], int Length)
 {
     int tmpData =0;
     int i=0;
     int j=0;
     int low;
     int high;
     int middle;
 
     for(i=1; i<Length; i++)
     {
         tmpData =SortData[i];
         low =0;
         high =i-1;
         //在r[low..high]中折半查找有序插入的位置
         while ( low<=high )
         {
             middle =(low+high)/2;
             if ( tmpData <SortData[middle] )
             {
                 high =middle-1;
             }
             else
             {
                 low =middle+1;
             }
         }
         //记录后移
         for (j=i-1; j>=high+1; j--)
         {
             SortData[j+1] =SortData[j];
         }
         SortData[high+1] =tmpData;
     }
 
     return;
 } 
 
 /*
 选择排序
 算法:首先找到数据清单中的最小的数据,然后将这个数据同第一个数据交换位置;接下来找第二小的数据,再将其同第二个数据交换位置,以此类推。
 所需移动的操作次数最少为0,,最大为3(n-1)
 然而无论记录的初始排列如何,需要比较的次数相同n(n-1)/2 复杂度为n*n
 */
 void SelectSortData(int SortData[], int Length)
 {
     int tmpData;
     int offset =0;
     int j=0;
 
     for (int i=0; i<Length-1; i++)
     {
         offset =0;
         tmpData =SortData[i];
         for (j=i+1; j<Length; j++)
         {
             if ( tmpData>SortData[j] )
             {
                 tmpData =SortData[j];
                 offset =j;
             }
         }
 
         if( offset >i)
         {
             SortData[offset] =SortData[i];
             SortData[i] =tmpData;
         }
     }
 
     return;
 }

template <class T > 
void ShellSort (T Vector[], int arrSize  ) {
    T temp;
    int gap = arrSize / 2;  //gap是子序列间隔	
    while ( gap != 0 ) {	          //循环,直到gap为零
        for ( int i = gap; i < arrSize; i++) {
            temp = Vector[i];	//直接插入排序
            for ( int j = i; j >= gap; j -= gap )
                if ( temp < Vector[j-gap] )
                    Vector[j] = Vector[j-gap];
                else break;          
              Vector[j] = temp;
        }				
        gap = ( int ) ( gap / 2 );
    }
}

/*归并排序
左边小左边,左边++;右边小取右边,右边++*/
template<typename T>
void merge(T array[], int low, int mid, int high)
{
	int k;
	T *temp = new T[high-low+1]; //申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
	int begin1 = low;
	int end1 = mid;
	int begin2 = mid + 1;
	int end2 = high;
	
	for (k = 0; begin1 <= end1 && begin2 <= end2; ++k)  //比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
	{
		if(array[begin1]<=array[begin2])
			temp[k] = array[begin1++];
		else
			temp[k] = array[begin2++];   
	}
		
    if(begin1 <= end1) //若第一个序列有剩余,直接拷贝出来粘到合并序列尾
		memcpy(temp+k, array+begin1, (end1-begin1+1)*sizeof(T));
    if(begin2 <= end2) //若第二个序列有剩余,直接拷贝出来粘到合并序列尾
		memcpy(temp+k, array+begin2, (end2-begin2+1)*sizeof(T));
    memcpy(array+low, temp, (high-low+1)*sizeof(T));//将排序好的序列拷贝回数组中

    delete temp;
}

template<typename T>
void merge_sort(T array[], unsigned int first, unsigned int last)
{
	int mid = 0;
	if(first<last)
	{
		//mid = (first+last)/2; /*注意防止溢出*/
		mid = first/2 + last/2;
		//mid = (first & last) + ((first ^ last) >> 1);
		merge_sort(array, first, mid);
		merge_sort(array, mid+1,last);
		merge(array,first,mid,last);
	}
}

/*堆排序
a[s]>=a[2*s] && a[s]>=a[2*s+1]*/
template<typename T>
void Max_heap(T a[],int S,int len)
{
	int l = 2*S;
	int r = 2*S+1;
	int maxI = S;
	T elem;
	if (l < len && a[l] > a[maxI])
	{
		maxI = l;
	}
	if (r < len && a[r] > a[maxI])
	{
		maxI = r;
	}
	if (maxI != S)
	{
		elem = a[S];
		a[S] = a[maxI];
		a[maxI] = elem;
		Max_heap(a,maxI,len);
	}
}

template<typename T>
void HeapSort(T a[],int n)
{
	int i;
	T elem;
	for (i = n/2;i>=0;i--)
	{
		Max_heap(a,i,n);
	}
	for (i= n-1;i>=1;i--)
	{
		elem = a[0];
		a[0] = a[i];
		a[i] = elem;
		n = n-1;
		Max_heap(a,0,n);
	}
}</span>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值