05-算法部分 (数据结构和算法)

一 排序算法

1.1 冒泡法排序

  • 冒泡排序(Bubble Sort)是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来

  • 首先从数组的第一个元素开始到数组最后一个元素为止,对数组中相邻的两个元素进行比较,如果位于数组左端的元素大于数组右端的元素,则交换这两个元素在数组中的位置。这样操作后数组最右端的元素即为该数组中所有元素的最大值。接着对该数组除最右端的n-1个元素进行同样的操作,再接着对剩下的n-2个元素做同样的操作,直到整个数组有序排列。

1.2 时间复杂度

冒泡法的时间复杂度为O(n^2)。

1.3 稳定性

冒泡法排序是一种稳定的算法

算法稳定性:假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!

1.4 实现

#include <stdio.h>
void bubble_sort(int arr[], int len) {int i, j, temp;for (i = 0; i < len - 1; i++)for (j = 0; j < len - 1 - i; j++)if (arr[j] > arr[j + 1]) {temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}
}
int main() {int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };int len = (int) sizeof(arr) / sizeof(*arr);bubble_sort(arr, len);int i;for (i = 0; i < len; i++)printf("%d ", arr[i]);return 0;
}

1.2 选择排序

1.2.1 基本逻辑

选择排序的基本思想描述为:

  • 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置

  • 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

  • 重复第二步,直到所有元素均排序完毕。

1.2.2 时间复杂度

选择排序的时间复杂度为O(n^2)。

1.2.3 稳定性

选择排序是一种不稳定的算法

1.2.4 实现

void swap(int *a,int *b) 
{int temp = *a;*a = *b;*b = temp;
}
void selection_sort(int arr[], int len)
{int i,j;for (i = 0 ; i < len - 1 ; i++){int min = i;for (j = i + 1; j < len; j++)   if (arr[j] < arr[min])  min = j;   swap(&arr[min], &arr[i]);  }
}

1.3 插入排序

1.3.1 基本逻辑

  • 插入排序的基本思想就是将无序序列插入到有序序列中。

  • 插入排序的的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

  • 步骤:

    • 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

    • 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

  • 图示:

    • 第一轮: 从第二位置的 6 开始比较,比前面 7 小,交换位置。

1.3.2 时间复杂度

插入排序的时间复杂度为O(n^2)。

1.3.3 稳定性

插入排序是稳定的排序算法

1.3.4 实现

void insertion_sort(int arr[], int len){int i,j,key;for (i=1;i<len;i++){key = arr[i];j=i-1;while((j>=0) && (arr[j]>key)) {arr[j+1] = arr[j];j--;}arr[j+1] = key;}
}

1.4 快速排序

1.4.1 基本逻辑

  • 快速排序的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,已达到整个序列有序。

  • 快速排序是一种分治法。

  • 一趟快速排序的具体过程可描述为:

    • 从数列中挑出一个元素,称为 "基准"(pivot);

    • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

    • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序

1.4.2 时间复杂度

平均时间复杂度为  O(nlog_2n)

1.4.3 稳定性

快排法是一种不稳定的排序算法。

1.4.4 实现

一趟快速排序的具体做法为:设置两个指针low和high分别指向待排序列的开始和结尾,记录下基准值baseval(待排序列的第一个记录),然后先从high所指的位置向前搜索直到找到一个小于baseval的记录并互相交换,接着从low所指向的位置向后搜索直到找到一个大于baseval的记录并互相交换,重复这两个步骤直到low=high为止。

// 快速排序
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);
}

1.5 归并排序

1.5.1 基本逻辑

  • 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。

  • “归并”的含义是将两个或两个以上的有序序列组合成一个新的有序表。假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,多个有序子序列,再两两归并。如此重复,直到得到一个长度为n的有序序列为止。这种排序方法称为2-路归并排序。

1.5.2 时间复杂度

归并排序的时间复杂度是O(n㏒n)。

但是,归并排序的空间复杂度是O(n)。

1.5.3 稳定性

归并排序是稳定的算法,它满足稳定算法的定义。

1.5.4 实现

#include<stdio.h>
#define ArrLen 20
void printList(int arr[], int len) {int i;for (i = 0; i < len; i++) {printf("%d\t", arr[i]);}
}
void merge(int arr[], int start, int mid, int end) {int result[ArrLen];int k = 0;int i = start;int j = mid + 1;while (i <= mid && j <= end) {if (arr[i] <= arr[j]){result[k++] = arr[i++];}else{result[k++] = arr[j++];}}if (i == mid + 1) {while(j <= end)result[k++] = arr[j++];}if (j == end + 1) {while (i <= mid)result[k++] = arr[i++];}for (j = 0, i = start ; j < k; i++, j++) {arr[i] = result[j];}
}void mergeSort(int arr[], int start, int end) {if (start >= end)return;int mid = ( start + end ) / 2;mergeSort(arr, start, mid);mergeSort(arr, mid + 1, end);merge(arr, start, mid, end);
}int main()
{int arr[] = {4, 7, 6, 5, 2, 1, 8, 2, 9, 1};mergeSort(arr, 0, 9);printList(arr, 10);system("pause");return 0;
}

1.6 常用排序算法总结

二、查找算法

2.1 二分查找法

2.1.1 基本逻辑

二分查找(Binary Search),也叫做折半查找,是一种在有序数组中查找某一特定元素的查找算法。查找过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则查找过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。

这种查找算法每一次比较都使查找范围缩小一半。

{5,13,19,21,37,56,64,75,80,88,92}采用折半查找算法查找关键字为 21 的过程为:

  • 找到中间值

  • 21比中间值小,则在左半部分找中间值

  • 比中间值大,则在右半部分找中间值

2.1.2 时间复杂度

折半查找每次把搜索区域减少一半,时间复杂度为 O(logn) 空间复杂度:O(1)

2.1.3 实现

递归实现:

#include<stdio.h>
#define SIZE 10
typedef int ElemType;
int refind(ElemType *data,int begin,int end,ElemType num);
int main(void){ElemType data[SIZE]={10,20,30,40,50,60,70,80,90,100};ElemType num;for(int i = 0;i<SIZE;i++)printf("%d ",data[i]);printf("\n请输入要查找的数据:\n");scanf("%d",&num);int flag = refind(data,0,SIZE,num);printf("位置为:%d\n",flag);return 0;
}
/
//递归
int refind(ElemType *data,int begin,int end,ElemType num)
{if(begin > end){printf("没找到\n");return -1;}int mid = (begin+end)/2;if(data[mid] == num){return mid;}else if(data[mid] <= num)return refind(data,mid+1,end,num);elsereturn refind(data,begin,mid-1,num);
}

非递归实现:

#include <stdio.h>int bin_search( int str[], int n, int key )
{int low, high, mid;low = 0;high = n-1;while( low <= high ){mid = (low+high)/2;if( str[mid] == key ){return mid;                // 查找成功}if( str[mid] < key ){low = mid + 1;        // 在后半序列中查找}if( str[mid] > key ){high = mid - 1;        // 在前半序列中查找}}return -1;                                // 查找失败
}int main()
{int str[11] = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89};int n, addr;printf("请输入待查找的关键字: ");scanf("%d", &n);addr = bin_search(str, 11, n);if( -1 != addr ){printf("查找成功, 关键字 %d 所在的位置是: %d\n", n, addr);}else{printf("查找失败!\n");}return 0;
}

2.2 不使用排序查找数组中第二大的值

2.2.1 思路

  • 定义最大值max初始化为a[0],第二大值为sec,遍历数组,如果数组元素比max大就更新,max=a[i],sec记录上一次max的值;

  • 如果数组元素不大于max,再将数组元素和sec判断,如果数组元素a[i]大于sec,则更新sec,sec=a[i]

2.2.2 代码实现

int secondbig(int data[],int N)
{int max=data[0],sec=0;for(int i=1;i<N;i++){if(max<data[i]){sec=max;max=data[i];}else{if(data[i]>sec){sec=data[i];}}} return sec;
}int main()
{int a[]={12,34,45,3,15,7,6,10};int sec = secondbig(a,8);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/21256.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5. Redis优化秒杀、Redis消息队列实现异步秒杀

文章目录 Redis优化秒杀、Redis消息队列实现异步秒杀一、秒杀优化1.1 回顾“一人一单”秒杀业务代码1.2 异步秒杀思路1.3 基于Redis完成秒杀资格判断1.3.1 修改VoucherServiceImpl1.3.2 Lua脚本编写1.3.3 Redislua判断用户是否抢购成功1.3.4 基于阻塞队列实现异步秒杀下单1.3.4…

python+requests接口自动化测试

原来的web页面功能测试转变成接口测试&#xff0c;之前大多都是手工进行&#xff0c;利用postman和jmeter进行的接口测试&#xff0c;后来&#xff0c;组内有人讲原先web自动化的测试框架移驾成接口的自动化框架&#xff0c;使用的是java语言&#xff0c;但对于一个学java&…

DaVinci Resolve Studio 18对Mac和Windows系统的要求

DaVinci Resolve Studio 18 是一款功能强大的专业视频编辑和调色软件&#xff0c;它提供了全面的工具和功能&#xff0c;让用户能够完成从剪辑、调色到特效和音频处理等各个方面的任务。DaVinci Resolve Studio 18 在中文界面上进行了优化&#xff0c;使得中文用户能够更加方便…

【C语言】约分最简式

题目描述&#xff1a; 分数可以表示为分子/分母的形式。编写一个程序&#xff0c;要求用户输入一个分数&#xff0c;然后将其约分为最简分式。最简分式是指分子和分母不具有可以约分的成分了。如6/12可以被约分为1/2。当分子大于分母时&#xff0c;不需要表达为整数又分数的形…

使用fast测试的错误

错误&#xff1a;Connection refused: connect 分析&解决 检查服务的端口号和fast生成请求时的端口号是否一致&#xff0c;不一致会报上面的错误 分析&#xff1a;设置服务配置的方法很多&#xff0c;可以写在配置文件里&#xff0c;也可以写在命令行里&#xff0c;当有多…

科目一速通技巧笔记,简记

常规 累计积分制度&#xff08;12满&#xff09;周期12月 虚假材料1年&#xff0c;假1吊二撤三醉五逃终身 假1500 骗三2k以下 初次领证1年实习期、实习标志&#xff0c;18~70岁 拼装车、报废车&#xff0c;吊销 200~2k 没有中心线&#xff08;一条路&#xff09;城市道路3…

keep-alive和router-view配合使用缓存整个路由页面以及路由切换

实现内容&#xff1a;通过vue实现&#xff0c;在页面有侧边栏动态来展示当前页面流程&#xff0c;右边进行页面的切换&#xff0c;左右两边都是组件&#xff0c;但是A/B/C组件的切换是通过keep-alive搭配router-view实现的&#xff0c;首先在当前文件中创建五个文件&#xff1a…

Hive SQL 迁移 Flink SQL 在快手的实践

摘要&#xff1a;本文整理自快手数据架构工程师张芒&#xff0c;阿里云工程师刘大龙&#xff0c;在 Flink Forward Asia 2022 生产实践专场的分享。本篇内容主要分为四个部分&#xff1a; Flink 流批一体引擎 Flink Batch 生产实践 核心优化解读 未来规划 点击查看原文视频…

2.Vue3中Cesium地图初始化及地图控件配置

前言 本文中&#xff0c;我们主要介绍 Cesium 在 Vue 3运行环境的配置&#xff0c;以及 Cesium 实例中控件的显隐设置&#xff0c;本文是后续文章内容的基础&#xff0c;项目代码在此查看&#xff1b;通过本文&#xff0c;我们可以得到一个纯净的 cesium 项目&#xff0c;后续的…

JMeter 中 3 种参数值的传递

目录 前言&#xff1a; (一) 从 CSV 文件读取要批量输入的变量 (二) 利用 Cookie 进行值的传递 (三) 利用正则匹配提取上一个接口的返回数据作为下个请求的输入 前言&#xff1a; 在JMeter中&#xff0c;参数值的传递是非常重要的&#xff0c;因为它允许你在测试过程中动态…

小区物业管理系统需求分析

小区物业管理系统核心在于加强管理&#xff0c;提升效率&#xff0c;降低成本。实现物业核心业务信息化&#xff0c;为员工提供流畅运营模式&#xff0c;为业主提供高品质服务&#xff0c;有助于公司做强做大&#xff0c;系统优势主要有以下几方面&#xff1a; • 服务数字化&a…

【网络系统集成】Windows Server集群实验

1.实验名称 Windows Server集群实验 2.实验目的 通过使用Windows 2003进行实验,理解与掌握服务器技术与系统集成相关知识点。 3.实验内容 (1)在Vmware Workstation中安装Windows Server 2003 (2)在Windows Server 2008中完成DNS,WEB的配置