排序算法總結

排序算法總結:

1.比較排序

  • 插入排序:直接插入,希爾排序
  • 選擇排序:直接選擇,堆排序
  • 交換排序:冒泡排序,快速排序 
  • 歸併排序

2.非比較排序

  • 計數排序

 

各自實現原理:

1.插入排序:遍歷整個數組,遍歷到每一位時,以這一位爲基準,往前遍歷,選擇合適的地方插入,不合適的元素往後移動

void InsertSort(int *arr, int size)
{
	for (int i = 0; i < size; i++)
	{
		int key = arr[i];
		int end = i - 1;
		while (key < arr[end])//end來標記該插入的位置
		{
			arr[end + 1] = arr[end];
			end--;
		}
		//到這裏已經找到插入的位置
		arr[end+1] = key;
	}
}

時間複雜度:O(N^2)

空間複雜度:O(1)

穩定性:穩定

適用場景:元素個數小  元素順序接近有序 

 

 

2.希爾排序: 使用間隔分組的方法插入排序    不穩定(隔着元素交換就不穩定)     如圖:

分成三組

void ShellSort(int *arr, int size)
{
	int grap = 3;
	while (grap--)
	{
		for (int i = grap; i < size; i++)
		{
			int key = arr[i];
			int end = i - grap;
			while (key < arr[end])//end來標記該插入的位置
			{
				arr[end + grap] = arr[end];
				end-=grap;
			}
			//到這裏已經找到插入的位置
			arr[end + grap] = key;
		}
	}
}

空間複雜度;O(1)

時間複雜度;取決於ret,間距

適用場景:量大,亂序

 

3.選擇排序:遍歷整個數組,找到最大的數和最小的數,最大的數放在最右邊,最小的數放在最左邊,(特殊情況特殊處理,比如最大的數剛好在最右邊,最小的數剛好早最右邊)  缺陷:進行重複比較

void SelectSort(int* arr, int size)
{
	int begin = 0;
	int end = size - 1;
	while (begin<end)
	{
		int maxpos = begin;
		int minpos = begin;
		int index = begin + 1;
		while (index <= end)
		{
			if (arr[index]>arr[maxpos])
			{
				maxpos = index;
			}
			if (arr[index] < arr[minpos])
			{
				minpos = index;
			}
			index++;
		}
		if (maxpos != end)
			swap(arr[maxpos], arr[end]);
		
		if (minpos == end)
			minpos = maxpos;		

		if (minpos != begin)
			swap(arr[minpos], arr[begin]);

		begin++;
		end--;
	}
}

 

4.冒泡排序:不穩定

void BubSort(int *arr, int size)
{
	int flag = 0;
	for (int i = 0; i < size-1; i++)
	{
		for (int j = 0; j < size - 1 - i; j++)
		{
			if (arr[j]>arr[j + 1])
			{
				flag = 1;
				swap(arr[j], arr[j + 1]);
			}
		}

		if (flag == 0)
		{
			break;
		}
	}
}

 

 

5.快速排序

//挖坑填數
int AdjustArray(int *arr, int left, int right)
{
	int i = left;
	int j = right;
	int s = arr[left];
	while (i < j)
	{
		while (i < j && arr[j] >= s)
			j--;
		if (i < j)		//這時從右往左找到小於基準值的數 
						//arr[i]爲上一次的坑 填arr[i] 然後遍歷i
		{
			arr[i] = arr[j];
			i++;
		}


		while (i < j && arr[i] <= s)
			i++;
		if (i < j)		//這時從左往右找到大於基準值的數 
						//arr[j]爲上一次的坑 填arr[j] 然後遍歷j
		{
			arr[j] = arr[i];
			j--;
		}
	}

	//此時從左往右遍歷完,arr[i]此時爲坑,將基準值填入,左邊的數全比基準值小,
	arr[i] = s;
	return i;

}



//分治
void quicksort(int *arr, int left, int right)
{
	if (left < right)
	{
		int ret = AdjustArray(arr, left, right);
		quicksort(arr, left, ret);
		quicksort(arr, ret + 1,right);
	}
}


int main()
{
	int arr[] = { 9, 7, 6, 4, 32, 1, 5, 9 };
	int size = sizeof(arr) / sizeof(arr[0]);
	quicksort(arr, 0, size-1);
	for (int i = 0; i < size;i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	system("pause");
	return 0;

 

6.堆排序

/**
 * 篩選位置i, 調整堆
 * @param a 待排序序列(數組)
 * @param i 篩選位置
 * @param len 數組元素個數
 */
void HeapAdjust(int a[], int i, int n)
{
    if(i > n / 2 - 1)
    {// 葉子結點, 無子樹
        return;
    }

    // 檢查結點i是否符合小堆特性, 如果不符合, 需要與最小子結點交換
    for(int k = 2*i +1; k < n; k = 2*k + 1)
    {
        // 判斷右子樹是否比左子樹更小
        if(k+1 < n && a[k+1] < a[k])
        {
            k ++; // 更新最小子結點
        }

        if(a[i] > a[k])
        {
            Swap(a[i], a[k]); // 與最小的子結點交換
            i = k;  // 將左子結點設爲當前結點
        }
        else
        {// 符合小堆特性
            break;
        }
    }
}

 

 

 

7.歸併排序

//合併兩個有序數組
void mergerarry(int *a, int first, int mid, int last, int *temp)
{
	int i = first, j = mid + 1;
	int m = mid, n = last;
	int k = 0;
	
	while (i <= m && j <= n)
	{
		if (a[i] <= a[j])
		{
			temp[k++] = a[i++];
		}
		else
		{
			temp[k++] = a[j++];
		}
	}

	//到這裏將剩餘的數填入
	while (i <= m)
	{
		temp[k++] = a[i++];
	}
	while (j <= n)
	{
		temp[k++] = a[j++];
	}
	for (i = 0; i < k; i++)
		a[first + i] = temp[i];
}

//分治 遞歸分組,然後依次向上合併
void mergersort(int *a, int first, int last, int *temp)
{
	if (first < last)
	{
		int mid = (first + last) / 2;
		mergersort(a, first, mid, temp);
		mergersort(a, mid+1, last, temp);
		mergerarry(a, first, mid, last, temp);
	}
}


//主調函數
bool Mergesort(int *a, int n)
{
	int *p = new int[n];
	if (p == NULL)
	{
		return false;
	}
	mergersort(a, 0, n - 1, p);
	delete[]p;
	return true;
}

int main()
{
	int arr[] = { 9, 7, 6, 4, 32, 1, 5, 9 };
	int size = sizeof(arr) / sizeof(arr[0]);
	Mergesort(arr, size);
	for (int i = 0; i < size;i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}

 

8.計數排序

//時間複雜度:O(N)--->N代表元素個數
//空間複雜度: O(M)--->M代表數據範圍 
void CountSort(int *arr, int size)
{
	int minValue = arr[0];
	int maxValue = arr[0];
	for (int i = 1; i < size; i++)
	{
		if (arr[i]>maxValue)
		{
			maxValue = arr[i];
		}

		if (arr[i] < minValue)
		{
			minValue = arr[i];
		}
	}
	//統計每個元素出現的次數
	int range = maxValue - minValue + 1;
	int *pCount = (int*)malloc(sizeof(int)*range);
	if (NULL == pCount)
	{
		return;
	}
	memset(pCount, 0, sizeof(int)*range);
	for (int i = 0; i < size; i++)
	{
		pCount[arr[i] - minValue]++; 
	}
	int index = 0;
	//排序 對pCount中的元素進行回收
	for (int i = 0; i < range; i++)
	{
		while (pCount[i])
		{
			arr[index++] = i + minValue;
			pCount[i]--;
		}
	}

	free(pCount);
}

int main()
{
	int arr[] = { 3, 4, 7, 1, 1, 0, 9, 8, 5, 2, 2, 5, 6 };
	int size = sizeof(arr) / sizeof(arr[0]);
	CountSort(arr, size);
	for (int i = 0; i < size; i++)
	{
		cout << arr[i] << " ";
	}
	
	cout << endl;
	system("pause");
	return 0;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章