首页 > 编程语言 >算法学习笔记

算法学习笔记

时间:2023-08-18 17:44:06浏览次数:45  
标签:node arr right int mid 笔记 学习 算法 left

来源

排序算法

冒泡排序

  • 遍历数组
  • 每次遍历到的元素和下一个元素比较,如果出现大于下一个,则交换
  • 一趟遍历就能使一个元素到它应当出现的地方
    图示:


图片源自知乎

代码:

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {     // 进行n-1轮排序,因为要和下一个比较所以n-1防止越界
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {    // 如果前面的数大于后面的数,则交换位置
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

插入排序

  • 第一个元素,我们默认有序
  • 取出下一个元素,扫描有序序列,将取出的元素放入有序序列的对应位置
  • 重复上一步骤
  • 直到最后一个元素也成为有序序列


图片源自知乎

代码:

void insertionSort(int *arr,int length){
	if( arr==null || length<2 ){
		return;
	}
	for(int i=1; i<length; ++i){//使得0~i有序
		//i就是新加入的元素,这个for循环是让有新的元素进来时仍然有序
		for(int j=i-1; j>=0 && arr[j]>arr[j+1]; --j){//检查新加入的元素,将其放到合适的位置
			//如果a[j]>a[j+1],则进行交换,否则循环停止
			int temp = arr[j];
			arr[j] = arr[j+1];
			arr[j+1] = temp;
		}
	}
}

选择排序

  • 遍历数组
  • 每次在没有排好序的部分找出当前最大/最小的元素放到排好序的部分对应的位置

代码:

void selectionSort(int arr[], int n) {
    int minIndex = 0;
    for (int i = 0; i < n - 1; ++i) {
	    minIndex = i;
        for(int j = i + 1; j < n; ++j){
		    if (arr[j]<arr[minIndex]){
			    minIndex = j;
		    } 
        }
        if(minIndex != i){
	        int temp = arr[i];
	        arr[i] = arr[minIndex];
	        arr[minIndex] = temp;
        }
}

查找算法

二分

  • 有序数组
  • 找到mid position,看mid position和我们要找的数据是不是一样
    • 防止溢出可以使用`mid = left + ((right - left) >>1 )
  • 找的数据更大,就去mid+1right中查找
  • 找的数据更小,就去leftmid-1中查找
  • 循环要求为left<right,如果left>right则说明没有符合要求的元素


图片源自知乎

int binarySearch(int *arr, int len, int val){
	int left = 0, right = len - 1;
	int mid = -1;
	while(left <= right){
		mid = left + ((right - left) >> 1);
		if(arr[mid] > val){
			right = mid -1;
		}else if(arr[mid] < val){
			left = mid + 1;
		}else{
			return mid;
		}
	}
	return -1;
}
int binarySearch(int arr[], int left, int right, int target) {
    if (left > right) {
        return -1; // 未找到目标元素
    }
    int mid = left + ((right - left) >> 1);
    if (arr[mid] == target) {
        return mid; // 找到目标元素
    } else if (arr[mid] > target) {
        return binarySearch(arr, left, mid - 1, target); // 在左半部分继续查找
    } else {
        return binarySearch(arr, mid + 1, right, target); // 在右半部分继续查找
    }
}

常见的数据结构

其实就是完全二叉树,或者就是从左到右开始的满二叉树

用数组存放完全二叉树,最上面放着最大的元素就是大根堆,放着最小的元素就是小根堆

  • 下标为i的元素,左孩子,如果不为空,则出现在i*2+1下标;右孩子如果不为空,则会出现在i*2+2下标

链表

以节点为单位,节点存储节点信息和下一个节点指针,以指针为连接处将不同节点穿起来

队列

普通队列先进先出;优先级队列底层由大/小根堆实现,先出最大/最小值

哈希表

unorder_set, unorder_map都是哈希表

  • 哈希表的增删改查无论数据多大,都是常数操作(比较大的常数,比直接寻址大得多)

二叉树的先序、中序、后序遍历

  • 先序:先头、再左,最后右
  • 中序:先左,再头,最后右
  • 后序:先左,再右,最后头
先序遍历
  1. 将非空节点压栈
  2. 出栈并打印
  3. 先将非空右子树节点压栈(空就不压)
  4. 再将非空左子树节点压栈(空就不压)
  5. 打印当前栈顶节点
  6. 重复3,4
std::vector<int> preorderTraversal(TreeNode *root) {  
  //先序  
  std::stack<TreeNode *> S;  
  TreeNode *node;  
  node = root;  
  std::vector<int> v;//输出序列  
  while (node || !S.empty()) {  
    if (node) {  
      v.push_back(node->val);//放入输入序列,相当于输出  
      S.push(node);  
      node = node->left;  
    } else {  
      node = S.top();//当前节点为空,node重新指向父节点然后输出,栈顶此时为最左边的元素  
      S.pop();  
      node = node->right;  
    }  
  }  
  return v;  
}
std::vector<int> preorderTraversal_(TreeNode *root) {  
  //先序  
  std::stack<TreeNode *> S;  
  TreeNode *node = root;  
  std::vector<int> V;  
  S.push(root);  
  while (!S.empty()) {  
    node = S.top();   
    S.pop();  
    V.push_back(node->val);  
    if (node->right != nullptr) {  
      S.push(node->right);  
    }  
    if (node->left != nullptr) {  
      S.push(node->left);  
    }  
  }  
  return V;  
}
中序遍历
  1. 将非空根节点压栈
  2. 将左节点压栈,直到没有左节点
  3. 弹栈,打印
  4. 将弹出的节点的右节点压栈(非空)
  5. 重复4,5
std::vector<int> inorderTraversal(TreeNode *root) {  
  //中序  
  // write code here  
  std::stack<TreeNode *> S;  
  TreeNode *node = root;  
  std::vector<int> V;  
  while (node || !S.empty()) {  
    if (node) {  
      S.push(node);  
      node = node->left;//从左子树开始,所以先找到最左边的数  
    } else {  
      node = S.top();//当节点为空后,此时栈顶为左子树为空的节点,  
      S.pop();  
      V.push_back(node->val);  
      node = node->right;  
    }  
  }  
  return V;  
}
后序遍历

和先序遍历有点像

std::vector<int> postorderTraversal(TreeNode *root) {  
//后序  
  std::stack<TreeNode *> S, S1;  
  TreeNode *node = root;  
  std::vector<int> V;  
  S.push(root);  
  while (!S.empty()) {  
    node = S.top();  
    S.pop();  
    S1.push(node);  
    if (node->left != nullptr) {  
      S.push(node->left);  
    }  
    if (node->right != nullptr) {  
      S.push(node->right);  
    }  
  }  
  //输出
  while (!S1.empty()) {  
    V.push_back(S1.top()->val);  
    S1.pop();  
  }  
  return V;  
}

标签:node,arr,right,int,mid,笔记,学习,算法,left
From: https://www.cnblogs.com/Lhh-9999/p/17641185.html

相关文章

  • 笔记整理--C语言--C语言指针5分钟教程——转载
    C语言指针5分钟教程指针、引用和取值什么是指针?什么是内存地址?什么叫做指针的取值?指针是一个存储计算机内存地址的变量。在这份教程里“引用”表示计算机内存地址。从指针指向的内存读取数据称作指针的取值。指针可以指向某些具体类型的变量地址,例如int、long和double。指针也可......
  • Microsoft Quantum Computing Fundamentals (MS QCF)​读书笔记
    1.学习目标准备开发环境,以便在Q#中编写量子程序。了解Q#程序的结构。使用量子比特和叠加来构建量子随机数生成器。了解Azure昆腾如何使你能够在量子硬件上运行程序。2.准备工作申请一个微软账号,会有500美金的免费额度用于创建工作区和量子使用费用。3.创建Azure量......
  • 【未完】Unity Revit与GLTF导出展示笔记
    Revit模型+材质Web网页加载显示......
  • 吴恩达机器学习2011版本学习笔记
    这是看完视频后,按自己的理解做了笔记。监督学习学的比较认真,33之后的无监督学习心态已经浮躁了,以后要再学一遍2022最新版视频课。1,有正确答案是有监督学习,反之是无监督学习2,模型就是把训练数据拟合为一个公式(严格来说是个函数,关系)。入门的拟合的方法是最小二乘法,先假设一个公式,......
  • 【学习笔记】简单数论-同余
    同余若整数\(a\)和整数\(b\)除以正整数\(m\)的余数相等,则称\(a,b\)模\(m\)同余,记为\(a\equivb\pmod{p}\)。性质自反性:\(a\equiva\pmod{p}\)对称性:若\(a\equivb\pmod{p}\),则\(b\equiva\pmod{p}\)。传递性:若\(a\equivb\pmod{p},b\equiv......
  • 【学习笔记】简单数论-快速幂
    luoguP1226【模板】快速幂|取余运算#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#definesortstable_sort#defineendl'\n'llqpow(lla,llb,llp){llans=1;while(b>0){if(b&1){......
  • 【学习笔记】简单数论-最大公约数
    一个整数\(N\)的约数上界为\(2\sqrt{N}\)。\(1\simN\)每个数的约数个数的总和大约为\(N\timeslogN\)。取模运算性质\((a+b)\bmodp=((a\bmodp)+(b\modp))\modp\),反之亦成立。\((a-b)\bmodp=((a\bmodp)-(b\modp))\modp\),反之亦成立。\((a\tim......
  • 【学习笔记】简单数论-质数
    质数的个数是无限的。试除法:若一个正整数\(N\)为合数,则存在一个能整除\(N\)的数\(T\),其中\(2\leT\le\sqrt{N}\)。时间复杂度为\(O(\sqrt{N})\)。代码实现boolisprime(intn){ if(n<2) returnfalse; for(inti=2;i<=sqrt(n);i++) if(n......
  • 燧光Rhino-X+Unity开发笔记
    一.前言  该文档的目的是记录开发过程中使用的燧光RhinoX眼镜和Unity引擎和所遇到的问题及解决方式。二.相关文档1.PhinoX-Unity开发文档2.官网设备介绍三.开发环境1.Unity2020.3.472.Rhino-For-Unity-2020Plugin四.问题列表1.RhinoX设备基本参数如下:  操作系统为......
  • 重新开始系统学习
    JavaJava并发包中Lock的实现原理SpringspringBead生命周期SpringBean和AOPAOP实现原理(动态代理和反射技术)JAVAAOP技术科普分享(上篇)技术科普  SpringCloud篇【SpringCloud】六大组件及作用eureka、zookepeer、nacos1eureka、zooKeeper、nacos2Dubbo......