算法与数据结构——排序

前提

void X_Sort (ElementType A[], int N)  //默认讨论从小到大的整数排序
  • 冒泡排序

void Bubble_Sort(ElementType A[], int N)
{
	for (int P = N - 1; P >= 0; P--)
	{
		int flag = 1;
		for (int i = 0; i < P; i++)
		{
			if (A[i] > A[i + 1])
			{
				Swap(A[i], A[i + 1]); //交换两数
				flag = 1;
			}
		}
		if (flag == 0) break;//无交换则退出
	}
}
  • 优点:比较稳定,不仅适用于数组,而且适用于单向链表

  • 插入排序

void Insert_Sort(ElementType A[], int N)
{
	int i;
	for (int p = 1; p < N; p++)
	{
		int Tmp = A[p];
		for ( i = p; i > 0 && A[i - 1] > Tmp; i--)
		{
			A[i] = A[i - 1];			
		}
		A[i] = Tmp;
	}
}

优点:稳定


  • 希尔排序

void Sheel_Sort(ElementType A[], int N)
{
	int i;
	for (int D = N / 2; D > 0; D /= 2)	//D为增量序列(此为最原始的希尔排序)
	{
		for (int P = D; P < N; P++)
		{
			int Tmp = A[P];
			for ( i = P; i >= D && A[i - D] > Tmp; i -= D)
			{
				A[i] = A[i - D];
			}
			A[i] = Tmp;
		}
	}
}

增量序列D因情况而异,特殊情况下互质的增量序列是没有效果的;


  • 选择排序

void Select_Sort(ElementType A[], int N)
{
	int minid;
	for (int i = 0; i < N; i++)
	{
		minid = i;
		for (int j = i + 1; j < N - 1; j++)
		{
			if (A[j] < A[minid])
			{
				minid = j;
			}
		}
		int tmp = A[i];
		A[i] = A[minid];
		A[minid] = tmp;
	}
}
  • 堆排序


  • 归并排序

  • 递归实现

void merge(ElementType A[], ElementType tempArr[], int left, int mid, int right)
{
	int L_pos = left;
	int R_pos = mid + 1;
	int pos = left;
	while (L_pos <= mid && R_pos <= right)
	{
		if (A[L_pos] < A[R_pos])
		{
			tempArr[pos++] = A[L_pos++];
		}
		else
		{
			tempArr[pos++] = A[R_pos++];
		}
	}
	while (L_pos <= mid)
	{
		tempArr[pos++] = A[L_pos++];
	}
	while (R_pos <= right)
	{
		tempArr[pos++] = A[R_pos++];
	}
	while (left <= right)
	{
		A[left] = tempArr[left];
		left++;
	}
}
void msort(ElementType A[], ElementType tempArr[], int left, int right) 
{
	if (left < right)
	{
		int mid = (left + right) / 2;
		msort(A, tempArr, left, mid);
		msort(A, tempArr, mid + 1, right);
		merge(A, tempArr, left, mid, right);
	}
}
void Merge_sort(ElementType A[], int N)
{
	//分配一个辅助数组
	int* tempArr = (int*)malloc(N * sizeof(ElementType));
	if (tempArr)
	{
		msort(A, tempArr, 0, N - 1);
                free(tempArr);
	}
	else
	{
		printf("error: failed to allocate memory");
	}
 
}
  • 非递归算法(循环实现)
/* L = 左边起始位置, R = 右边起始位置, RightEnd = 右边终点位置*/
void Merge( ElementType A[], ElementType TmpA[], int L, int R, int RightEnd )
{ /* 将有序的A[L]~A[R-1]和A[R]~A[RightEnd]归并成一个有序序列 */
     int LeftEnd, NumElements, Tmp;
     int i;
      
     LeftEnd = R - 1; /* 左边终点位置 */
     Tmp = L;         /* 有序序列的起始位置 */
     NumElements = RightEnd - L + 1;
      
     while( L <= LeftEnd && R <= RightEnd ) {
         if ( A[L] <= A[R] )
             TmpA[Tmp++] = A[L++]; /* 将左边元素复制到TmpA */
         else
             TmpA[Tmp++] = A[R++]; /* 将右边元素复制到TmpA */
     }
 
     while( L <= LeftEnd )
         TmpA[Tmp++] = A[L++]; /* 直接复制左边剩下的 */
     while( R <= RightEnd )
         TmpA[Tmp++] = A[R++]; /* 直接复制右边剩下的 */
    //   该过程可忽略   
   //  for( i = 0; i < NumElements; i++, RightEnd -- )
     //    A[RightEnd] = TmpA[RightEnd]; /* 将有序的TmpA[]复制回A[] */
}
 
void Merge_pass( ElementType A[], ElementType TmpA[], int N, int length )
{ /* 两两归并相邻有序子列 */
     int i, j;
       
     for ( i=0; i <= N-2*length; i += 2*length )   //只两两归并到倒数第二组,尾巴的情况要单独考虑
         Merge( A, TmpA, i, i+length, i+2*length-1 );
     if ( i+length < N ) /* 归并最后2个子列*/
         Merge( A, TmpA, i, i+length, N-1);
     else /* 最后只剩1个子列*/
         for ( j = i; j < N; j++ ) TmpA[j] = A[j];
}
 
void Merge_Sort( ElementType A[], int N )
{ 
     int length; 
     ElementType *TmpA;
      
     length = 1; /* 初始化子序列长度*/
     TmpA = malloc( N * sizeof( ElementType ) );
     if ( TmpA != NULL ) {
          while( length < N ) {
              //循环使用A[]和TmpA[],节省了Merge()函数中每次都要将TmpA中有序数组复制回A的过程
              Merge_pass( A, TmpA, N, length );
              length *= 2;
              Merge_pass( TmpA, A, N, length );
              length *= 2;
          }
          free( TmpA );
     }
     else printf( "空间不足" );
}

未完待续。。。。。

posted @ 2020-10-09 19:30  与谁  阅读(120)  评论(0编辑  收藏  举报