栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

直接插入排序、希尔排序、简单选择排序、堆排序、冒泡、快速排序代码实现

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

直接插入排序、希尔排序、简单选择排序、堆排序、冒泡、快速排序代码实现

一、插入类排序:

1.直接插入排序

#include
void print(int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("n");
}

void insertSort(int a[], int n)
{
	int i, j;
	for ( i = 1; i < n; i++)
	{
		int key = a[i];
       //注意有等号则算法就不稳定了
		for ( j = i - 1; j >= 0 && a[j] > key; j--)
		{
			a[j + 1] = a[j];

		}
		a[j + 1] = key;
	}
}

int main()
{
	printf("插入排序:n");
	int a[] = { 2,4,6,8,10,1,3,5,7,9 };
	print(a, sizeof(a) / sizeof(a[0]));
	insertSort(a, 10);
	print(a, sizeof(a) / sizeof(a[0]));

	return 0;

}

2.希尔排序

//方式一
#include
void print(int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("n");
}
void shellSort(int a[], int n)
{
	int gap = 3;
	int i, j;
	while (gap--)
	{
		for ( i = gap; i < n; i++)
		{
			int key = a[i];
			for ( j = i - gap; j >= 0 && a[j] > key; j-=gap)
			{
				a[j + gap] = a[j];
			}
			a[j + gap] = key;
		}
	}
}

int main()
{
	int a[] = { 2,4,6,8,10,1,3,5,7,9 };
	printf("希尔排序:n");
	print(a, sizeof(a) / sizeof(a[0]));
	shellSort(a, 10);
	print(a, sizeof(a) / sizeof(a[0]));

	return 0;

}



//方式二(注意gap差别)

#include
void print(int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("n");
}

void shellSort(int a[], int n)

{
	int gap = n;
	while (gap>1)
	{
		   gap = gap / 3 + 1;
			int i, j;
				
		 //int i, j;
     //这里i++而不是i+gap原因是比较下一组(隔相同步数的为一组)
		for ( i = gap; i < n; i++)
		{
		 int key = a[i];
		    for (j = i - gap; j >= 0 && key < a[j]; j-=gap)
			{
				a[j + gap] = a[j];
			}
			a[j + gap] = key;
		}

			//gap--;
	}
	
}

int main()
{
	int a[] = { 1,3,5,7,9,2,4,6,8,10 };
	printf("希尔排序:n");
	print(a, sizeof(a) / sizeof(a[0]));
	shellSort(a, sizeof(a) / sizeof(a[0]));
	print(a, sizeof(a) / sizeof(a[0]));
	return 0;

}

二、选择类排序

1.简单选择排序

//方式一--先排最大的,即将最大的排在后面
#include
void print(int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("n");
}

void selectSort(int a[], int n)
{
	int i, j;
	for ( i = 0; i < n - 1; i++)
	{
		//max为当前最大值下标,从下标为0到下标为max-1中找最大的,不断更新max
		int max = n-1-i;
		for (j = 0; j < n - 1 - i; j++)
		{
			if (a[j] > a[max])
			{
				max = j;
			}
		}
			
			if (max != j)
			{	
				int temp = a[j];
			    a[j] = a[max];
			    a[max] = temp;
			}
	}
}


//或用以下写法





int main()
{
	int a[] = { 1,3,5,7,9,2,4,6,8,10 };
	printf("选择排序:n");
	print(a, sizeof(a) / sizeof(a[0]));
	selectSort(a, sizeof(a) / sizeof(a[0]));
	print(a, sizeof(a) / sizeof(a[0]));
	return 0;
}



//方式二--先排最小的,即将最小的放在前面

#include
void print(int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("n");
}

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



}

int main()
{
	int a[] = { 1,3,5,7,9,2,4,6,8,10 };
	printf("选择排序:n");
	print(a, sizeof(a) / sizeof(a[0]));
	selectSort(a, sizeof(a) / sizeof(a[0]));
	print(a, sizeof(a) / sizeof(a[0]));
	return 0;
}




//方式三--在一趟中同时找最大和最小元素,将最大元素和最小元素进行交换
#include
#include

void swap(int* a, int* b)
{
	int t = *a;
	*a = *b;
	*b = t;
}

void PrintArray(int array[], int size)
{
	for (int i = 0; i < size; ++i)
	{
		printf("%d ", array[i]);
	}

	printf("n");
}

void SelectSort(int* a, int n)
{
	assert(a);
	int begin = 0, end = n - 1;
	while (begin < end)
	{
		int min = begin, max = begin;
		for (int i = begin; i <= end; i++)
		{
			if (a[i] >= a[max])
				max = i;


			if (a[i] < a[min])
				min = i;
		}
		//最小的放在
		swap(&a[begin], &a[min]);
		//如果最大的位置在begin位置
		//说明min是和最大的交换位置
		//这个时候max的位置就发生了变换
		//max变到了min的位置
		//所以要更新max的位置
		if (begin == max)
			max = min;


		swap(&a[end], &a[max]);
		++begin;
		--end;


		//PrintArray(a, n);
	}
}


int main()
{
	int a[] = { 3, 4, 6, 1, 2, 8, 0, 5, 7 };
	SelectSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
	return 0;
}

2.堆排序

#include
void print(int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("n");
}

//n表示父节点,size表示总节点个数
void adjustDown(int a[], int size, int n)
{
	//n相当于parent
	int child = n * 2 + 1;
	while (child < size)
	{

		//若要排降序,只要该为a[child+1] a[child])
		{
			child = child + 1;
		}

		if (a[child] > a[n])
			{
				int temp = a[child];
				a[child] = a[n];
				a[n] = temp;
				n = child;
			    child = child * 2 + 1;
			}
		else
		{
			return;
		}

	}
}

	void heapSort(int a[], int n)
	{
		//建堆
		for (int i = (n - 2) / 2; i >= 0; i--)
		{
			adjustDown(a, n, i);
		}

		//利用堆删除思想排序
		int end = n - 1;
		while (end)
		{
			int temp = a[0];
			a[0] = a[end];
			a[end] = temp;
			
			//heapSort(a, end);
			//上一次end的下标刚好是下一次要排的元素个数
			adjustDown(a, end, 0);
			end--;
		}

	}

	int main()
	{

		int a[] = { 1,3,5,7,9,2,4,6,8,10 };
		printf("堆排序:n");
		print(a, sizeof(a) / sizeof(a[0]));
		heapSort(a, sizeof(a) / sizeof(a[0]));
		print(a, sizeof(a) / sizeof(a[0]));
		return 0;


	}

三、交换类排序

1.冒泡排序

#include
void print(int a[], int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("n");
}

void bubbleSort(int a[], int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int flag = 1;
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (a[j + 1] < a[j])
			{
				int temp = a[j + 1];
				a[j + 1] = a[j];
				a[j] = temp;
				flag = 0;
			}
		}
		if (flag == 1)
		{
			break;
		}
	}
}

   int main()
   {
	   int a[] = { 2,4,6,8,10,1,3,5,7,9 };
	   printf("冒泡排序:n");
	   print(a, sizeof(a) / sizeof(a[0]));
	   bubbleSort(a, sizeof(a) / sizeof(a[0]));
	   print(a, sizeof(a) / sizeof(a[0]));
	   return 0;
   }

2.快速排序

//有三种方式取基准值,分别是PartSort1、PartSort2、PartSort3
#include
#include
#include
#include

typedef int DataType;

// 动态
typedef struct Stack
{
	DataType* array;
	int capacity;
	int top;  // 标记栈顶---实际就是顺序表中的有效元素的个数
}Stack;


void StackInit(Stack* ps,int n)
{
	assert(ps);

	ps->array = (DataType*)malloc(sizeof(DataType) * n);
	if (NULL == ps->array)
		assert(0);

	ps->capacity = n;
	ps->top = 0;
}

void StackCheckCapacity(Stack* ps)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		int newCapacity = (ps->capacity << 1);

		// 1. 开辟新空间
		DataType* temp = (DataType*)malloc(sizeof(DataType) * newCapacity);
		if (NULL == temp)
			assert(0);

		// 2. 拷贝元素
		memcpy(temp, ps->array, sizeof(DataType) * ps->capacity);

		// 3. 释放旧空间,使用新空间
		free(ps->array);
		ps->array = temp;
		ps->capacity = newCapacity;
	}
}


// 入栈---尾插
void StackPush(Stack* ps, DataType data)
{
	StackCheckCapacity(ps);

	ps->array[ps->top] = data;
	ps->top++;
}

// 检测栈是否为空,如果为空返回真,否则返回假
int StackEmpty(Stack* ps)
{
	assert(ps);
	return 0 == ps->top;
}

// 出栈
void StackPop(Stack* ps)
{
	if (StackEmpty(ps))
		return;

	ps->top--;
}

// 获取栈顶元素
DataType StackTop(Stack* ps)
{
	assert(ps);
	// return ps->array[--ps->top];  // 错误写法
	return ps->array[ps->top - 1];  // 正确的

}


void PrintArray(int array[], int size)
{
	for (int i = 0; i < size; ++i)
	{
		printf("%d ", array[i]);
	}

	printf("n");
}

void swap(int* a, int* b)
{
	int t = *a;
	*a = *b;
	*b = t;
}

// 三数取中法,三个中取一个中间值

int GetMidIndex(int* a, int begin, int end)
{
	int mid = begin + ((end - begin) >> 1);
	if (a[begin] < a[mid])
	{
		if (a[mid] < a[end])
		{
			return mid;
		}
		else if (a[begin] > a[end])
		{
			return begin;
		}
		else
		{
			return end;
		}
	}
	else // begin >= mid
	{
		if (a[mid] > a[end])
		{
			return mid;
		}
		else if (a[begin] < a[end])
		{
			return begin;
		}
		else
		{
			return end;
		}
	}

}

int PartSort1(int* a, int begin, int end)
{
	int midindex = GetMidIndex(a, begin, end);
	swap(&a[begin], &a[midindex]);

	int key = a[begin];
	int start = begin;
	
	while (begin < end)
	{
		// end 找小
		while (begin < end && a[end] >= key)
			--end;

		// begin找大
		while (begin < end && a[begin] <= key)
			++begin;

		swap(&a[begin], &a[end]);
	}
	//最后的交换一定要保证a[begin] < a[start], 所以要从右边走
	swap(&a[begin], &a[start]);
	return begin;
}

int PartSort2(int* a, int begin, int end)
{
	//begin是坑
	int key = a[begin];
	while (begin < end)
	{
		while (begin < end && a[end] >= key)
			--end;

		// end给begin这个坑,end就变成了新的坑。
		a[begin] = a[end];

		while (begin < end && a[begin] <= key)
			++begin;

		// end给begin这个坑,begin就变成了新的坑。
		a[end] = a[begin];
	}

	a[begin] = key;

	return begin;
}



int PartSort3(int* a, int begin, int end)
{
	int midindex = GetMidIndex(a, begin, end);
	swap(&a[begin], &a[midindex]);

	int key = a[begin];
	int prev = begin;
	int cur = begin + 1;

	while (cur <= end)
	{
		// cur找小,把小的往前翻,大的往后翻
		if (a[cur] < key && ++prev != cur)
			swap(&a[cur], &a[prev]);

		++cur;
	}

	swap(&a[begin], &a[prev]);

	return prev;
}

void insertSort(int a[], int n)
{
	int j;
	for (int i = 1; i < n; i++)
	{
		int temp = a[i];
		for (j = i - 1; a[j] > temp && j >= 0; j--)
		{

			a[j + 1] = a[j];

		}
		a[j + 1] = temp;
	}

}



void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;

	if (right - left + 1 < 10)
	{
		insertSort(a + left, right - left + 1);
	}
	else
	{
		int div = PartSort1(a, left, right);
		//[left, div-1]
		//[div+1, right]
		QuickSort(a, left, div - 1);
		QuickSort(a, div + 1, right);
	}
}
//用栈模拟递归,用队列也可以实现
void QuickSortNor(int array[], int size)
{
	Stack s;
	StackInit(&s,10);

	int left = 0;
	int right = size;

	StackPush(&s, right);
	StackPush(&s, left);

	while (!StackEmpty(&s))
	{
		left = StackTop(&s);
		StackPop(&s);
		right = StackTop(&s);
		StackPop(&s);

		if (right - left <= 16)
			insertSort(array + left, right - left);
		else
		{
			int div = PartSort2(array, left, right);

			// 基准值的左侧:[left, div)
			// 基准值的右侧:[div+1, right);
			StackPush(&s, right);
			StackPush(&s, div + 1);

			StackPush(&s, div);
			StackPush(&s, left);
		}
	}
}




int main()
{
	int a[] = { 3, 4, 6, 1, 2, 8, 0, 5, 7 };
	printf("快速排序:n");
	PrintArray(a, sizeof(a) / sizeof(int));
	//QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);
	QuickSortNor(a,  sizeof(a) / sizeof(int) );
	PrintArray(a, sizeof(a) / sizeof(int));
	return 0;
}

四、归并排序:

//有递归和非递归两种方式,已测试
#include
#include
#include
#include

void PrintArray(int array[], int size)
{
	for (int i = 0; i < size; ++i)
	{
		printf("%d ", array[i]);
	}

	printf("n");
}

void _MergeSort(int* a, int left, int right, int* tmp)
{
	if (left >= right)
		return;

	int mid = left + ((right - left) >> 1);

	// [left, mid]
	// [mid+1, right]
	_MergeSort(a, left, mid, tmp);
	_MergeSort(a, mid + 1, right, tmp);

	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int index = left;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] <= a[begin2])
			tmp[index++] = a[begin1++];
		else
			tmp[index++] = a[begin2++];
	}

	while (begin1 <= end1)
	{
		tmp[index++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[index++] = a[begin2++];
	}

	memcpy(a + left, tmp + left, sizeof(int) * (right - left + 1));
}

//封装一下,让用户好调用
void MergeSort(int* a, int n)
{
	assert(a);
	int* tmp = (int*)malloc(sizeof(int) * n);
	_MergeSort(a, 0, n - 1, tmp);
	free(tmp);
}


void merge(int* a, int left, int mid, int right, int* tmp)
{
	// [left, mid]
	// [mid+1, right]
	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int index = left;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] <= a[begin2])
			tmp[index++] = a[begin1++];
		else
			tmp[index++] = a[begin2++];
	}

	while (begin1 <= end1)
	{
		tmp[index++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[index++] = a[begin2++];
	}

	memcpy(a + left, tmp + left, sizeof(int) * (right - left + 1));
}


void mergePass(int* arr, int k, int n, int* temp)
{
	int i = 0;
	//从前往后,将2个长度为k的子序列合并为1个
	while (i < n - 2 * k + 1)
	{
		merge(arr, i, i + k - 1, i + 2 * k - 1, temp);
		i += 2 * k;
	}
	//合并区间[i, n - 1]有序的左半部分[i, i + k - 1]以及不及一个步长的右半部分[i + k, n - 1]
	if (i < n - k)
	{
		merge(arr, i, i + k - 1, n - 1, temp);
	}

}

// 归并排序非递归版
void MergeSortNonR(int* arr, int length)
{
	int k = 1;
	int* temp = (int*)malloc(sizeof(int) * length);
	while (k < length)
	{
		mergePass(arr, k, length, temp);
		k *= 2;
	}
	free(temp);
}

int main()
{
	int a[10] = { 4,1,3,2,7,6,5,9,10,8 };
	printf("归并排序:n");
	PrintArray(a, 10);
	MergeSort(a, 10);
	PrintArray(a, 10);

	//printf("归并排序--非递归:n");
	//MergeSortNonR(a, 10);
	//PrintArray(a, 10);
	return 0;
}

五、计数排序:

#include
#include
#include
#include
void PrintArray(int array[], int size)
{
	for (int i = 0; i < size; ++i)
	{
		printf("%d ", array[i]);
	}

	printf("n");
}

void CountSort(int* a, int n)
{
	int max = a[0], min = a[0];
	for (int i = 0; i < n; ++i)
	{
		if (a[i] > max)
			max = a[i];

		if (a[i] < min)
			min = a[i];
	}
	//找到数据的范围 
	int range = max - min + 1;
	int* countArray = (int*)malloc(range * sizeof(int));
	memset(countArray, 0, sizeof(int) * range);
	//存放在相对位置,可以节省空间
	for (int i = 0; i < n; ++i)
	{
		countArray[a[i] - min]++;
	}
	//可能存在重复的数据,有几个存几个
	int index = 0;
	for (int i = 0; i < range; ++i)
	{
		while (countArray[i]--)
		{
			a[index++] = i + min;
		}
	}
}

//该方式好理解
void CountSort2(int array[], int size)
{
	// 0. 获取数据的范围
	int minValue = array[0];
	int maxValue = array[0];
	for (int i = 1; i < size; ++i)
	{
		if (array[i] > maxValue)
			maxValue = array[i];

		if (array[i] < minValue)
			minValue = array[i];
	}

	// 数据范围在[minValue, maxValue] 假设数据在1000-1009,其实只需要10个空间就可以
	int range = maxValue - minValue + 1;

	int* count = (int*)calloc(range, sizeof(int));
	if (NULL == count)
	{
		assert(0);
		return;
	}

	// 1. 先统计每个元素出现的次数
	for (int i = 0; i < size; ++i)
	{
		count[array[i] - minValue]++;
	}

	// 2. 排序--按照计数数组的下标对数据进行回收
	int index = 0;
	for (int i = 0; i < 10; ++i)
	{
		// 回收
		while (count[i] > 0)
		{
			array[index++] = i + minValue;//展开
			count[i]--;
		}
	}

	free(count);
}

int main()
{
	int a[10] = { 4,1,3,2,7,6,5,9,10,8 };
	printf("计数排序:n");
	PrintArray(a, 10);
	CountSort2(a, 10);
	PrintArray(a, 10);
	return 0;

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/835314.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号