数据结构_排序算法(c语言)

 

目录

 

1、冒泡排序 

思想:

时间复杂度:

源代码c:

2、选择排序

思想:

时间复杂度

源代码c:

3、插入排序

思想:

时间复杂度

源代码c

4、希尔排序(插入排序的改进)

思想:

时间复杂度:

源代码c:

5、堆排序(选择排序的改进)

堆排序的基本思想:

时间复杂度:

源代码c:

6、归并排序(递归实现)

思想:

时间复杂度:

源代码c:

7、快速排序(冒泡排序的改进)

思想:

时间复杂度:

源代码c:


1、冒泡排序 

思想:

让数组当中相邻的两个数进行比较,数组当中比较小的数值向上浮,数值比较大的向下沉!外层for循环控制循环次数,内层for循环控制相邻的两个元素进行比较。

例:4 1 5 2

第一次:1 4 2 5

第二次:1 2 4 5 

第三次:1 2 4 5

时间复杂度:

O(n^{2})

源代码c:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 5

void bubble_sort(int k[], int n)
{
	int i, j, temp;
	for (i = 0; i < n - 1; i++)      //外循环表示比较n-1轮
	{
		for (j = 0; j < n-1-i; j++)     //内循环表示每轮比较结束后,最后一个值最大,每轮除去最后一个继续比较
		{
			if (k[j] > k[j+1])
			{
				temp = k[j];
				k[j] = k[j+1];
				k[j+1] = temp;
			}
		}
	}
}

int main()
{
	int k[N];
	int i;
    srand((unsigned int)time(NULL));
	for(i=0;i<N;i++)
		k[i] = rand() % N;
	bubble_sort(k,N);

	for(i=0;i<N;i++)
		printf("%d ",k[i]);

	printf("\n");
    system("pause");   //可以实现冻结屏幕,便于观察程序的执行结果
	return 0;
}
//改进的冒泡排序
#include<stdio.h>
#include<stdlib.h>
#define N 5

void bubble_sort(int k[], int n)
{
	int i, j, temp,flag = 1;
	for (i = 0; i < n - 1 && flag; i++)      //外循环表示比较n-1轮
	{
        flag=0;
		for (j = 0; j < n-1-i; j++)     //内循环表示每轮比较结束后,最后一个值最大,每轮除去第一个继续比较(从后往前比)
		{
			if (k[j] > k[j+1])
			{
                flag=1;
				temp = k[j];
				k[j] = k[j+1];
				k[j+1] = temp;
			}
		}
	}
}

int main()
{
	int k[N];
	int i;
	for(i=0;i<N;i++)
		scanf("%d",&k[i]);
	bubble_sort(k,N);

	for(i=0;i<N;i++)
		printf("%d ",k[i]);

	printf("\n");
    system("pause");   //可以实现冻结屏幕,便于观察程序的执行结果
	return 0;
}

 

2、选择排序

思想:

时间复杂度

O(n^{2})

源代码c:

#include<stdio.h>
#include<stdlib.h>

void select(int k[], int n)
{
	int i, j, temp, min;
	for (i = 0; i < n - 1; i++)      //外循环表示选择n-1轮
	{
		min = i;
		for (j = i + 1; j < n; j++)     //内循环挑选最小的值,下标赋值给min
		{
			if (k[j] < k[min])
				min = j;
		}
		if (min != i)
		{
			temp = k[i];
			k[i] = k[min];
			k[min] = temp;
		}
	}
	printf("\n");
}

int main()
{
	int i, k[10] = { 2, 5, 7, 9, 0, 1, 2, 4, 3, 6 };
	select(k, 10);
	for (i = 0; i < 10; i++)
		printf("%d ", k[i]);
	system("pause");   //可以实现冻结屏幕,便于观察程序的执行结果
	return 0;
}

 

3、插入排序

思想:

时间复杂度

O(n^{2})

源代码c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<time.h>
#define N 20


void PrintArray(int arr[], int len)   //输出函数
{ 
	for (int i = 0; i < len; i++)
		printf("%d ", arr[i]);
	printf("\n");
}

void InsertSort(int arr[], int len) //插入排序将数据分为有序和无序两部分
{
	int i, j, temp;
	for (i = 1; i < len; i++)       //外循环--无序部分
	{
		temp = arr[i];
		if (arr[i] < arr[i - 1])    
		{
			for (j = i - 1; j >= 0 && arr[j] > temp; j--)     //内循环,将无序插入到有序
			{
				arr[j + 1] = arr[j];
			}
			arr[j + 1] = temp;
		}
	}

}

int main(){
	int arr[N];
	srand((unsigned)time(NULL));
	for (int i = 0; i < N; i++){
		arr[i] = rand() % N;
	}

	PrintArray(arr, N);
	InsertSort(arr, N);
	PrintArray(arr, N);
	system("pause");
	return 0;

}

 

4、希尔排序(插入排序的改进)

思想:

将数组中每间隔为d的元素划分为同一组,然后对每一组使用插入排序。d有多个值,但要求最后一个值为1,即最后一次要进行插入排序。例如数组:2 9 1 3 6 3,如果d为2,那么2、1、6为一组;9、3、3为一组;对每组都进行插入排序。

时间复杂度:

O(n*logn)

源代码c:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<time.h>
#define N 10

void PrintArray(int arr[], int len)
{
	for (int i = 0; i < len; i++)
		printf("%d ", arr[i]);
	printf("\n");
}

void ShellSort(int arr[], int len)
{
	int i, j, k, temp,increasement = len;
	do{
		increasement = increasement / 3 + 1;  //确定分的组数,最后组数为1
		for (i = 0; i < increasement; i++)     //遍历每组
		{
			for (j = i + increasement; j < len; j += increasement)  //每组分别进行插入排序
			{
				if (arr[j] < arr[j - increasement])
				{
					temp = arr[j];
					for (k = j - increasement; k >= 0 && arr[k] > temp; k -= increasement)
					{
						arr[k + increasement] = arr[k];
					}
					arr[k + increasement] = temp;
				}
			}
		}
	} while (increasement > 1);
}

int main()
{
	int arr[N];
	srand((unsigned)time(NULL));
	for (int i = 0; i < N; i++)
    {
		arr[i] = rand() % N;      //得到0--N-1的随机数
	}
	PrintArray(arr, N);
	ShellSort(arr, N);
	PrintArray(arr, N);
	system("pause");
	return 0;
}

 

5、堆排序(选择排序的改进)

顶堆的介绍:

  • 大顶堆:每个节点的值都大于或者等于它的左右子节点的值。arr[i] >= arr[2i ] && arr[i] >= arr[2i +1]
  • 小顶堆:每个节点的值都小于或者等于它的左右子节点的值。arr[i] <= arr[2i ] && arr[i] <= arr[2i +1]

堆排序的基本思想:

  1. 将待排序的序列构造成一个大顶堆,根据大顶堆的性质,当前堆的根节点(堆顶)就是序列中最大的元素;
  2. 将堆顶元素和最后一个元素交换,然后将剩下的节点重新构造成一个大顶堆;
  3. 重复步骤2,如此反复,从第一次构建大顶堆开始,每一次构建,我们都能获得一个序列的最大值,然后把它放到大顶堆的尾部。最后,就得到一个有序的序列了。
     

时间复杂度:

O(n*logn)

源代码c:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

//打印函数
void PrintArray(int arr[], int len)
{
	for (int i = 0; i < len; i++)
		printf("%d ", arr[i]);
	printf("\n");
}

//交换数组中的两个元素
void swap(int arr[], int a, int b)
{
	int temp = arr[a];
	arr[a] = arr[b];
	arr[b] = temp;
}

void HeapAdjust(int arr[], int index, int len)
{
	//保存当前节点的下标
	int max = index;

	//保存左右孩子的下标
	int lchild = index * 2 + 1;
	int rchild = index * 2 + 2;

	if (lchild<len&&arr[lchild]>arr[max])
		max = lchild;
	if (rchild<len&&arr[rchild]>arr[max])
		max = rchild;
	if (max != index)
	{
		//交换两个结点
		swap(arr, max, index);
		HeapAdjust(arr, max, len);
	}
}

void HeapSort(int arr[], int len)
{
	for (int i = len / 2 - 1; i >=0 ; i--)
	{
		//初始化堆
		HeapAdjust(arr, i, len);  //刚开始从下往上调整
	}

	//交换顶堆元素和最后一个元素
	for (int i = len - 1; i >=0 ; i--)
	{
		swap(arr, 0, i);
		HeapAdjust(arr, 0, i);   //从上往下调整
	}
}

int main(){
	int arr[10] = { 8, 6, 5, 7, 9, 0, 1, 2, 4, 3 };
	int len = sizeof(arr) / sizeof(int);
	PrintArray(arr, len);

	//堆排序
	HeapSort(arr,len);
	PrintArray(arr, len);
	system("pause");
	return 0;
}

 

6、归并排序(递归实现)

思想:

先分组:将一个无需数组分成多个有序数组

再合并:利用辅助空间将两个有序数组合并成一个有序数组,再覆盖原数组

详细“治”的步骤:

时间复杂度:

O(n*logn)

源代码c:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<time.h>

#define N 10

//打印函数
void PrintArray(int arr[], int len)
{
	for (int i = 0; i < len; i++)
		printf("%d ", arr[i]);
	printf("\n");
}

//创建数组
int* CreatArray()
{
	srand((unsigned int)time(NULL));
	int* arr = (int*)malloc(sizeof(int)*N);
	for (int i = 0; i < N; i++)
		arr[i] = rand() % N;
	return arr;
}

//合并算法(将两个有序数组合并成一个有序数组)
void Merge(int arr[], int start, int end, int mid, int* temp)//辅助空间
{
	int i_start = start;
	int i_end = mid;
	int j_start = mid + 1;
	int j_end = end;
	int k = 0;//记录辅助空间当前元素数量

	while (i_start <= i_end && j_start <= j_end)
	{
		if (arr[i_start] < arr[j_start])
		{
			temp[k++] = arr[i_start];
			i_start++;
		}
		else
		{
			temp[k++] = arr[j_start];
			j_start++;
		}
	}
	while (i_start <= i_end)   //左半边多余
	{
		temp[k++] = arr[i_start];
		i_start++;
	}
	while (j_start <= j_end)  //右半边多余
	{
		temp[k++] = arr[j_start];
		j_start++;
	}

	//辅助空间数据覆原空间
	for(int i = 0; i < k; i++)
		arr[start + i] = temp[i];
}

//归并排序
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);

	//合并
	Merge(arr, start, end, mid, temp);
}

int main(){
	int *arr = CreatArray();
	PrintArray(arr, N);

	//辅助空间
	int* temp = (int*)malloc(sizeof(int)*N);

	MergeSort(arr, 0, N - 1,temp);
	PrintArray(arr, N);

	//释放空间
	free(temp);
	free(arr);
	system("pause");
	return 0;
}

 

7、快速排序(冒泡排序的改进)

思想:

时间复杂度:

O(n*logn)

最坏情况:O(n^2)

源代码c:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

void PrintArray(int arr[], int len)
{
	for (int i = 0; i < len; i++)
		printf("%d ", arr[i]);
	printf("\n");
}

void QuickSort(int arr[], int start, int end)
{
	int i = start, j = end;
	int temp = arr[start];  //基准数
	if (i < j)
	{
		while (i < j)
		{
			while (i<j && arr[j] >= temp)  //从右向左,找小于temp的
			{
				j--;
			}
			if (i < j)     //填坑
			{
				arr[i] = arr[j];
				i++;
			}

			while (i<j && arr[i] < temp)  //从左向右,找大于temp的
			{
				i++;
			}
			if (i < j)      //填坑
			{
				arr[j] = arr[i];
				j--;
			}
		}
		arr[i] = temp;                  //把基准数放到 i=j 位置
		QuickSort(arr, start, i - 1);   //左半部分快排 
		QuickSort(arr, i + 1, end);     //右半部分快排
	}
}

int main(){
	int arr[10] = { 8, 6, 5, 7, 9, 0, 1, 2, 4, 3 };
	int len = sizeof(arr) / sizeof(int);

	PrintArray(arr, len);
	QuickSort(arr, 0, len - 1);
	PrintArray(arr, len);
	system("pause");
	return 0;

}
  • 0
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值