一般的に使用されるソートアルゴリズムの7種類

1、バブルソート

ソートアルゴリズムの最もシンプルなタイプ。昇順に配置され、長さNの配列ARRと仮定する。バブルソートの手順を詳述し、以下のように記述することができる:まず、最初から配列の最後の要素への配列の最初の要素、二つの隣接する要素の配列を比較して、配列の配列要素の左端に位置する要素が右端よりも大きい場合、その後、アレイ内の2つの要素のスイッチ位置は、この時点ですべての要素の最大値は、配列の要素の右端の配列です。バブルソートアレイ全体規則正しいアレイまで、n-1個の残りの要素が続きます。アルゴリズムの時間計算量はO(N ^ 2)です。

// 冒泡排序
void BubbleSort(int arr[], int length)
{
	for (int i = 0; i < length; i++)
	{
		for (int j = 0; j < length -  i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp;
				temp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = temp;
			}
		}
	}
}

2. [ソート

ヤンウェイミン版「データ構造」は、基本的な考え方は、ソートを選択することである説明:各パスにおけるN-I + 1(iが= 1,2、...、N-1)最小記録として選択された番目の記録キーをi番目の記録シーケンスを命じました。具体的には、位置は、アレイ(すなわち、等しくないMIN1のARR [左端最小MIN1でない場合、Nの昇順に配置されるアレイARRの長さは、次に、N個のデジタルMIN1最小の開始は、検出されたと仮定すると0])、次いで最小MIN1とARR [0]を交換し、その後、残りのn-1個の数の最小値MIN2を見つけ、最小値MIN2のARR [1]に等しくない場合、これら2つの数の交換、ように、配列arrが注文したまで。アルゴリズムの時間計算量はO(N ^ 2)です。

void  fun(int a[], int n)
{ int p, temp;
  for (int i = 0; i < n-1; i++) 
  {
    p = i;
    for (int j = i; j < n; j++)
      if(a[p] > a[j])
        p = j;
    temp = a[p];
	a[p] = a[i]; 
	a[i] = temp;
  }
}

void main()
{
  int a[N];
  printf("输入数据:\n") ;
  for(int i = 0; i < N; i++) 
	  scanf("%d",&a[i]);
  fun(a,N);
  printf("排序后的数据:\n") ;
  for(int i = 0; i < N; i++) 
	  printf("%5d ",a[i]); 
  printf("\n");
}

3、挿入ソート

 基本的な考え方の挿入ソートは、順序付けられたシーケンスに無秩序配列に対してです。例えば、配列ARR = [4,2,8,0,5,1]ソーティングに、図4は、順序付けられたシーケンスとして見ることができる(図は青色で示されている)、[2,8,0,5 、1]ランダムシーケンスとして扱わ。ランダムシーケンスは4の左側に、インサート2、次いで、24よりも小さい場合、この時間は、配列がランダム配列[8,0,5,1]に、[2,4]となる順序付けられました。ランダムシーケンスは、右4にインサート8は、順序付けられたシーケンスとなり、[2,4,8]より大きく84であり、ランダムシーケンスは[0,5,1]となります。昇順に及びそう、最終的に配列。アルゴリズムの時間計算量はO(N ^ 2)です。

// 插入排序
void InsertSort(int arr[], int length)
{
	for (int i = 1; i < length; i++)
	{
		int j;
		if (arr[i] < arr[i - 1])
		{
			int temp = arr[i];
			for (j = i - 1; j >= 0 && temp < arr[j]; j--)
			{
				arr[j + 1] = arr[j];
			}
			arr[j + 1] = temp;
		}
	}
}

4、ヒルソート

丘挿入ソートアルゴリズムに基づいて、改善された(シェルの並べ替え)をソートアルゴリズムの時間複雑度は以前いくつかのアルゴリズム大きな改善と比較されます。アルゴリズムの基本的な考え方は次のとおりいくつかのサブシーケンス挿入ソート配列に分割され記録される最初の行、直接挿入ソートすべてのレコードに対して一旦配列全体にわたって記録される「実質的に順序付けられた」、としています。

// 插入排序
void ShellSort(int arr[], int length)
{
	int increasement = length;
	int i, j, k;
	do
	{
		// 确定分组的增量
		increasement = increasement / 3 + 1;
		for (i = 0; i < increasement; i++)
		{
			for (j = i + increasement; j < length; j += increasement)
			{
				if (arr[j] < arr[j - increasement])
				{
					int temp = arr[j];
					for (k = j - increasement; k >= 0 && temp < arr[k]; k -= increasement)
					{
						arr[k + increasement] = arr[k];
					}
					arr[k + increasement] = temp;
				}
			}
		}
	} while (increasement > 1);
}

  5、クイックソート

基本的なアイデアはすぐにソートすることで2つの独立した部分、レコード・キーがレコードの他の部分よりも小さくなっている、あなたは、二つの部分のそれぞれは、ソートに引き続き記録することができますの重要な部分に分割する放電記録への旅でソートこれは、全体のシーケンス順序に達しています。特定トリップクイックソート処理は次のように記述することができる基準値として任意の列からソートする(通常は最初のレコードを選択する)レコードを選択する前に、それはその場所に配置されているレコードのレコード・キーよりも小さいですその大きなレコードに比べレコードキーは、その位置の後ろに配置されています。従って、参照は、2つの配列のカラムにソートする、境界線です。

具体的にはクイックソートトリップ2つのポインタは、それぞれ、低および高になる点提供、開始及びソートカラムの端部は、次いで、(最初の列をソートするレコード)が基準値BASEVALを記録位置が高いと呼ば開始しますそれはレコードがBASEVAL為替より大きいと、低=ハイアップまで、これらの2つのステップを繰り返すことで見つかるまでの場所から、あなたは見つけることの少ない記録BASEVAL為替よりも前方まで検索し、低バック検索を指摘しました。

// 快速排序
void QuickSort(int arr[], int start, int end)
{
	if (start >= end)
		return;
	int i = start;
	int j = end;
	// 基准数
	int baseval = arr[start];
	while (i < j)
	{
		// 从右向左找比基准数小的数
		while (i < j && arr[j] >= baseval)
		{
			j--;
		}
		if (i < j)
		{
			arr[i] = arr[j];
			i++;
		}
		// 从左向右找比基准数大的数
		while (i < j && arr[i] < baseval)
		{
			i++;
		}
		if (i < j)
		{
			arr[j] = arr[i];
			j--;
		}
	}
	// 把基准数放到i的位置
	arr[i] = baseval;
	// 递归
	QuickSort(arr, start, i - 1);
	QuickSort(arr, i + 1, end);
}

6、マージソート

二つ以上の組み合わせが新しい順序付きリストにシーケンスを命じたことを「マージ」を意味します。これは、nは、長さ1の各サブシーケンスは、次に、長さ2の(以下X以上の最小の整数を表す)二十から二ギブをマージサブシーケンスを注文通りに見ることができ、初期シーケンスをnレコードが含まれているものと(または1)配列を注文し、その後二十から二マージ。n個の順序付けられたシーケンスまでの長さになるまで繰り返します。この配列決定法は、2ウェイマージソートと呼ばれています。

// 归并排序
void MergeSort(int arr[], int start, int end, int * temp)
{
	if (start >= end)
		return;
	int mid = (start + end) / 2;
	MergeSort(arr, start, mid, temp);
	MergeSort(arr, mid + 1, end, temp);
 
	// 合并两个有序序列
	int length = 0; // 表示辅助空间有多少个元素
	int i_start = start;
	int i_end = mid;
	int j_start = mid + 1;
	int j_end = end;
	while (i_start <= i_end && j_start <= j_end)
	{
		if (arr[i_start] < arr[j_start])
		{
			temp[length] = arr[i_start]; 
			length++;
			i_start++;
		}
		else
		{
			temp[length] = arr[j_start];
			length++;
			j_start++;
		}
	}
	while (i_start <= i_end)
	{
		temp[length] = arr[i_start];
		i_start++;
		length++;
	}
	while (j_start <= j_end)
	{
		temp[length] = arr[j_start];
		length++;
		j_start++;
	}
	// 把辅助空间的数据放到原空间
	for (int i = 0; i < length; i++)
	{
		arr[start + i] = temp[i];
	}
}

7ヒープソート

/*
	@param arr 待调整的数组
	@param i 待调整的结点的下标
	@param length 数组的长度
*/
void HeapAdjust(int arr[], int i, int length)
{
	// 调整i位置的结点
	// 先保存当前结点的下标
	int max = i;
	// 当前结点左右孩子结点的下标
	int lchild = i * 2 + 1;
	int rchild = i * 2 + 2;
	if (lchild < length && arr[lchild] > arr[max])
	{
		max = lchild;
	}
	if (rchild < length && arr[rchild] > arr[max])
	{
		max = rchild;
	}
	// 若i处的值比其左右孩子结点的值小,就将其和最大值进行交换
	if (max != i)
	{
		int temp;
		temp = arr[i];
		arr[i] = arr[max];
		arr[max] = temp;
		// 递归
		HeapAdjust(arr, max, length);
	}
}
 
// 堆排序
void HeapSort(int arr[], int length)
{
	// 初始化堆
	// length / 2 - 1是二叉树中最后一个非叶子结点的序号
	for (int i = length / 2 - 1; i >= 0; i--)
	{
		HeapAdjust(arr, i, length);
	}
	// 交换堆顶元素和最后一个元素
	for (int i = length - 1; i >= 0; i--)
	{
		int temp;
		temp = arr[i];
		arr[i] = arr[0];
		arr[0] = temp;
		HeapAdjust(arr, 0, i);
	}
}

 

公開された407元の記事 ウォンの賞賛150 ビュー380 000 +

おすすめ

転載: blog.csdn.net/ds1130071727/article/details/103240589