常见排序算法

常见排序算法

中间函数

#include<stdio.h>

// 如果使用这种方式进行数据交换的话,在传入同一个元素地址进行元素交换时,
//会导致a=b=0,因为都是对同一个地址中的内容进行操作。
void swape(int* a,int* b) 
{
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}


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

1.冒泡排序

/*
*函数名:冒泡排序
*参数:数组名,数组长度
*思路:简单一点就是有几个数就进行几轮排序,在每轮排序中对所有数值进行前后比较,每一轮比较下来就会有一个数值的位置是可以确定的
*缺点:一般来说到了最后几轮的排序,数值基本上都是排好序了的,所以容易造成运行时间的浪费
*改进:可以在每一轮的比较排序中,增加标志位,如果在该轮的比较中进行了数值的交换,就将标志位置为1,否则就将标志位置为0,
*然后在进行新一轮比较时,检查标志位如果为1,则在进行新一轮比较,否则就break;
*/

/*
* 
*函数名:冒泡排序
*参数:数组名,数组长度
*思路:简单一点就是有几个数就进行几轮排序,在每轮排序中对所有数值进行前后比较,每一轮比较下来就会有一个数值的位置是可以确定的
*缺点:一般来说到了最后几轮的排序,数值基本上都是排好序了的,所以容易造成运行时间的浪费
*改进:可以在每一轮的比较排序中,增加标志位,如果在该轮的比较中进行了数值的交换,就将标志位置为1,负责就为0,
*然后在进行新一轮比较时,检查标志位是否为1,如果是则在进行新一轮比较,负责就break;
*/

void Bubble_Sort(int* arr, int len)
{
	int temp = 0;
	int flag = 1;
	for (int i = 1; i < len; i++)
	{
		if(flag)
		{ 
			flag = 0;
			for (int j = 0; j < len - 1 -i; j++) {
				
				if (arr[j]) > arr[j + 1]) {
				
					swape(arr[j], arr[j + 1]);
					flag = 1;
				}
			}
			
			printf("第%d次排序:\n",i);
			print(arr, len);
		}
		else
		{
			break;
		}
		
	}
	printf("\n");
}

2.选择排序

/*
* 函数名:选择排序
* 函数参数:数组名arr,数组长度len
* 思路:进行len-1轮循环,每轮循环找出最大(最小)的值,放到已排序好的数组的末尾
*一开始也就是将找到的最大(小)的元素放到首位置,
*然后再将在第二轮找到的最大(小)值放到首位置的后面位置,以此类推.....
*/

void Select_Sort(int* arr, int len)
{
    int index = 0;
    for (int i = 0; i < len - 1; i++) 
    {
        index = i;
        for (int j = i + 1; j < len; j++) 
        {
            if (arr[j]) < arr[index]) {
                index = j; //记录此轮循环中最小值的下标
            }
        }
        if(i != index)swape(arr[i]), (arr[index]); //将此轮循环的最小值放到已排序序列的末尾位置
        printf("第%d次排序:\n", i+1);
        print(arr, len);
    }
    printf("\n");
}

3.插入排序

/*
*函数名:插入排序
*函数参数:数组名arr,数组长度len
*思路:将无序数值,插入有序数值,从后往前扫描。
*(刚开始就将第一个元素看作的有序的,然后将第二元素与第一个元素进行比较排序,
*此时就可以得到一个由两个数值组成的有序数组了,
* 然后将第三个元素插入到有序数组中,以此类推.....)
* 
*
*/

void Insert_Sort(int* arr, int len)
{
    int i = 0, j = 0;
    int temp = 0;
    for (int i = 1; i < len; i++)
    {
        temp = arr[i];
        j = i - 1;

        while (j >= 0 && arr[j] > temp) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j+1] = temp;

        printf("第%d次排序:\n", i);
        print(arr, len);
    }
}

4.快速排序

/*
*函数名:寻找基准元素下标,在寻找的同时也会对传入的数组值,进行基于基准值的左右划分
*
*/
static int i = 0;
int Find_Pivot_Index(int* arr, int left, int right)
{
    int L = left, R = right;
    int pivot = arr[left];  //选择最左边的元素作为基准值

    while (L != R) {  
        while (arr[R] >= pivot && L < R) {  //从最右边开始扫描,如果比基准值大,就不断向左移动
            R--;
        }
        arr[L] = arr[R];  //到了这里,说明在基准值右边碰到了一个比它小的,所以就把比基准值小的放到其左边
        while (arr[L] <= pivot && L < R) {  //到了这里,说明在从右往左扫描的时候,遇到了比基准值小的数值,所以开始从左向右扫描
            L++;
        }
        arr[R] = arr[L]; // 到了这步,说明在左边遇到一个比基准值大的元素,所以要将其值放到右边
    }
    arr[L] = pivot;  //此时L=R,所以将pivot放到基准位置,这样的话,0 ~ L-1 的元素都比pivot小, L+1  ~ right 的元素都比pivot大。

    printf("第%d次排序:\n", i++);
    print(arr, right-left);

    return L;
}


/*
*函数名:快速排序
*函数参数:数组名arr,数组长度len
*思路:核心就是在算法中不断调用 寻找基准元素值下标 的函数,然后在根据 基准元素值下标值,将数组进行划分,再将划分之后的数组传入快速排序算法
* 在调用 寻找基准元素值下标 函数时,不仅会返回基准元素值下标,而且也会对数组中的元素进行划分,不断根据基准值进行数组划分,而且用的都是同一个数组,所以每次
* 快速排序的结果都会在同一个数组中体现,只不过每次传入的不是整个数组,而是数组的一部分,这就是分治思想。
*/
void Quick_Sort(int* arr, int left, int right)
{
    if (left < right) {
        int pivot_index = Find_Pivot_Index(arr, left, right);
        Quick_Sort(arr, left, pivot_index - 1);
        Quick_Sort(arr, pivot_index + 1, right);
    }
    
}

  

测试

int main(void)
{
	int arr[10] = { 2,96,8,5,6,4,3,1,7,25 };
	printf("原始数组:\n");
	print(arr, 10);
	Bubble_Sort(arr, 10); //冒泡排序
	//Select_Sort(arr, 10); //选择排序
	//Insert_Sort(arr, 10);//插入排序
	//Quick_Sort(arr, 0, 9);//快速排序
	printf("排序结束:\n");
	print(arr, 10);
	return 0;
}

算法复杂度

时间复杂度空间复杂度稳定性算法
最情况
平均情况
最坏情况

O(n)

O(n^2)

O(n^2)

O(1)稳定冒泡

O(n^2)

O(n^2)

O(n^2)

O(1)不稳定选择

O(n)

O(n^2)

O(n^2)

O(1)稳定插入

O(n *log n)

O(n *log n)

O(n^2)

O(log n)不稳定快速

概念讲解:

时间复杂度:算法执行过程中总的基本操作次数

空间复杂度:算法执行过程所需要的额外存储空间

算法稳定性:排序前后两个相等的数相对位置不变,则算法稳定。

查找算法

1.顺序查找

/*
*函数名:顺序查找
* 思路:从前往后依次查找,需要查找的值,最后返回该值的下标
*/

int Sequential_Search(int* arr,int target_value,int len)
{
	int i = 0;
	while (i < len) {
		if (arr[i] == target_value)return i + 1;
		++i;
	}
	return 0;
}


2.折半查找

/*
*前提:所传入的数组必须是有序的
*非递归实现
*/
int Binary_Search(int* arr, int low, int high, int target_vale)
{
	int mid;
	while (low <= high) {
		mid = low + (high - low) / 2;
		if (arr[mid] == target_vale) return mid + 1;
		else if (arr[mid] > target_vale) {
			high = mid - 1;
		}
		else {
			low = mid + 1;
		}
	}
}
/*
*递归实现
*/
int Binary_Search1(int* arr, int low, int high,int target_vale)
{
	
	if (low > high)return -1;
	int mid = low + (high - low) / 2;
	if (arr[mid] == target_vale)return mid+1;

	if (low <= high) {
		if (arr[mid] >  target_vale) {
			high = mid - 1;
			return Binary_Search(arr,  low, high, target_vale);
		}
		else if (arr[mid] <  target_vale) {
			low = mid + 1;
			return Binary_Search(arr, low, high, target_vale);
		}
	}
}

字符操作相关算法

1.复制字符串

//字符串复制函数
void Str_copy(char* DesStr, const char* SrcStr) {
	while (*DesStr++ = *SrcStr++);
	*DesStr = '\0';

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值