【大话数据结构算法】查找算法
顺序查找
针对无序序列的一种最简单的查找方式。
算法思想:
从表中第一个记录开始,逐个与给定值进行比较,若某个记录的关键字和给定值相等,则查找成功;反之,若直到最后一个记录,其关键字和给定值都不相等,则表明表中没有所查记录,查找失败。
由于我们不清楚这个数据判断究竟需要多少次。但是我们知道,这种数据查找最少需要1次,最多需要n次,平均查找长度为(1+n)/2。顺序查找算法的时间复杂度为O(n)。
二分/折半查找(有序表)
算法思想:
先确定待查记录所在的范围,然后逐步缩小范围,直到找到或者找不到记录为止。
普通的数据查找算法复杂度是O(n)。下面我们来分析一下二分查找的复杂度。这种方法最小是1次,最多需要log(n+1)/log2即可。很明显,这种数据查找的效率要比前面的查找方法高很多。
java实现代码如下(二分查找 && 顺序查找):
public class Search {public static void main(String[] args) {int[] array = {3,5,7,9,1,2,0};System.out.println(find(array, 7, 9));}//顺序查找public static int find(int[] array,int length,int value){if (null == array || 0 == length) {return -1;}for (int index = 0; index < array.length; index++) {if (array[index] == value) {return index;}}return -1;}//二分查找public static int binarySort(int[] array,int length,int value){if (null == array || 0 == length) {return -1;}int start = 0;int end = length - 1;while(start <= end){int middle = (end + start) / 2;//这个地方还有问题if (array[middle] == value) {return middle;}else if (array[middle] < value) {start = middle + 1;}else{end = middle - 1;} }return -1;}}
排序二叉树(B树)
顺序查找和二分查找都是建立在连续内存基础之上的,如果是指针类型的数据就要引入排序二叉树了。
排序二叉树定义:
1、非叶子结点至少一边的分支非空;
2、叶子节点左右分支都为空;
3、每一个节点记录一个数据,同时左分支的数据都小于右分支的数据。
4、排序二叉树中序遍历得到的必定是一个有序序列。
排序二叉树查找过程:
1、若查找树为空,查找失败;
2、若查找树非空,将给定值和查找树的根节点比较:
若相等,查找成功,结束查找过程;
若给定值小于根节点,查找将在根节点的左子树上继续进行,转至1;
若给定值大于根节点,查找将在根节点的右子树继续进行,转至1;
时间复杂度:平均O(logn),最坏O(n)
排序二叉树的插入:
新插入的节点一定是一个新添加的叶子节点,并且是查找不成功时查找路径上访问的最后一个节点的左孩子或右孩子节点。
排序二叉树的节点删除:
假设在排序二叉树上需要被删除的节点为p,且p为f的左孩子,下面分三种情况讨论:
1、若p节点为叶子节点,即pl和pr均为空树,由于删去叶子节点不破坏整棵树的结构,则只需修改其双亲结点的指针即可;
2、若p节点只有左子树pl或者只有右子树pr,此时只要令pl和pr直接成为其双亲结点f的左子树即可;
3、若p节点的左子树和右子树均不空。
C实现排序二叉树:
/*************************************************************************排序二叉树,实现了以下操作:插入结点、构造二叉树、删除结点、查找、查找最大值、查找最小值、查找指定结点的前驱和后继。上述所有操作时间复杂度均为o(h),其中h是树的高度
*************************************************************************/#include<stdio.h>
#include<stdlib.h>//二叉查找树结点描述
typedef int KeyType;
typedef struct Node
{KeyType key; //关键字struct Node * left; //左孩子指针struct Node * right; //右孩子指针struct Node * parent; //指向父节点指针
}Node,*PNode;//往二叉查找树中插入结点
//插入的话,可能要改变根结点的地址,所以传的是二级指针
void inseart(PNode * root,KeyType key)
{//初始化插入结点PNode p=(PNode)malloc(sizeof(Node));p->key=key;p->left=p->right=p->parent=NULL;//空树时,直接作为根结点if((*root)==NULL){*root=p;return;}//插入到当前结点(*root)的左孩子if((*root)->left == NULL && (*root)->key > key){p->parent=(*root);(*root)->left=p;return;}//插入到当前结点(*root)的右孩子if((*root)->right == NULL && (*root)->key < key){p->parent=(*root);(*root)->right=p;return;}if((*root)->key > key)inseart(&(*root)->left,key);else if((*root)->key < key)inseart(&(*root)->right,key);elsereturn;
}//查找元素,找到返回关键字的结点指针,没找到返回NULL
PNode search(PNode root,KeyType key)
{if(root == NULL)return NULL;if(key > root->key) //查找右子树return search(root->right,key);else if(key < root->key) //查找左子树return search(root->left,key);elsereturn root;
}//查找最小关键字,空树时返回NULL
PNode searchMin(PNode root)
{if(root == NULL)return NULL;if(root->left == NULL)return root;else //一直往左孩子找,直到没有左孩子的结点return searchMin(root->left);
}//查找最大关键字,空树时返回NULL
PNode searchMax(PNode root)
{if(root == NULL)return NULL;if(root->right == NULL)return root;else //一直往右孩子找,直到没有右孩子的结点return searchMax(root->right);
}//查找某个结点的前驱
PNode searchPredecessor(PNode p)
{//空树if(p==NULL)return p;//有左子树、左子树中最大的那个if(p->left)return searchMax(p->left);//无左子树,查找某个结点的右子树遍历完了else{if(p->parent == NULL)return NULL;//向上寻找前驱while(p){if(p->parent->right == p)break;p=p->parent;}return p->parent;}
}//查找某个结点的后继
PNode searchSuccessor(PNode p)
{//空树if(p==NULL)return p;//有右子树、右子树中最小的那个if(p->right)return searchMin(p->right);//无右子树,查找某个结点的左子树遍历完了else{if(p->parent == NULL)return NULL;//向上寻找后继while(p){if(p->parent->left == p)break;p=p->parent;}return p->parent;}
}//根据关键字删除某个结点,删除成功返回1,否则返回0
//如果把根结点删掉,那么要改变根结点的地址,所以传二级指针
int deleteNode(PNode* root,KeyType key)
{PNode q;//查找到要删除的结点PNode p=search(*root,key);KeyType temp; //暂存后继结点的值//没查到此关键字if(!p)return 0;//1.被删结点是叶子结点,直接删除if(p->left == NULL && p->right == NULL){//只有一个元素,删完之后变成一颗空树if(p->parent == NULL){free(p);(*root)=NULL;}else{//删除的结点是父节点的左孩子if(p->parent->left == p)p->parent->left=NULL;else //删除的结点是父节点的右孩子p->parent->right=NULL;free(p);}}//2.被删结点只有左子树else if(p->left && !(p->right)){p->left->parent=p->parent;//如果删除是父结点,要改变父节点指针if(p->parent == NULL)*root=p->left;//删除的结点是父节点的左孩子else if(p->parent->left == p)p->parent->left=p->left;else //删除的结点是父节点的右孩子p->parent->right=p->left;free(p);}//3.被删结点只有右孩子else if(p->right && !(p->left)){p->right->parent=p->parent;//如果删除是父结点,要改变父节点指针if(p->parent == NULL)*root=p->right;//删除的结点是父节点的左孩子else if(p->parent->left == p)p->parent->left=p->right;else //删除的结点是父节点的右孩子p->parent->right=p->right;free(p);}//4.被删除的结点既有左孩子,又有右孩子//该结点的后继结点肯定无左子树(参考上面查找后继结点函数)//删掉后继结点,后继结点的值代替该结点else{//找到要删除结点的后继q=searchSuccessor(p);temp=q->key;//删除后继结点deleteNode(root,q->key);p->key=temp;}return 1;
}//创建一棵二叉查找树
void create(PNode* root,KeyType *keyArray,int length)
{int i;//逐个结点插入二叉树中for(i=0;i<length;i++)inseart(root,keyArray[i]);
}int main(void)
{int i;PNode root=NULL;KeyType nodeArray[11]={15,6,18,3,7,17,20,2,4,13,9};create(&root,nodeArray,11);for(i=0;i<2;i++)deleteNode(&root,nodeArray[i]);printf("%d\n",searchPredecessor(root)->key);printf("%d\n",searchSuccessor(root)->key);printf("%d\n",searchMin(root)->key);printf("%d\n",searchMax(root)->key);printf("%d\n",search(root,13)->key);return 0;
}
【大话数据结构算法】查找算法相关推荐
- 【Java】 大话数据结构(13) 查找算法(4) (散列表(哈希表))
本文根据<大话数据结构>一书,实现了Java版的一个简单的散列表(哈希表). 基本概念 对关键字key,将其值存放在f(key)的存储位置上.由此,在查找时不需比较,只需计算出f(key) ...
- 数据结构–七大查找算法总结
查看全文 http://www.taodudu.cc/news/show-3546957.html 相关文章: C语言实现基础查找算法 查找算法--顺序查找 微信小程序之算法查询 Idea 配置git ...
- 数据结构之查找算法:顺序查找
查找算法:顺序查找 思维导图: 顺序查找的定义: 顺序查找的代码实现: 顺序查找的性能: 思维导图: 顺序查找的定义: 顺序查找的代码实现: typedef struct { //查找表数据结构int ...
- 【数据结构】查找算法
文章目录 查找算法 顺序查找算法 折半查找 分块查找 二叉排序树 平衡二叉树(AVL树) 散列表 哈希函数的构造 处理冲突的方法 哈希查找算法及其实现 查找算法 查找:在数据集合中寻找满足某种条件的数 ...
- 数据结构与算法-查找算法(二分查找,插值查找,斐波那契(黄金分割法)查找)
查找算法 以下三种算法的基本思想相同,都是利用递归来寻找 二分查找 思路分析 1.首先确定该数组的中间下标,min = (left + right) / 2 2.然后让需要查找的的数findVal和a ...
- 数据结构——四大查找算法(工作必备)
在java中,常用的查找有四种 顺序(线性)查找 二分查找折半查找 插值查找 斐波那契查找 目录 1. 线性查找 2. 二分查找 3. 插值查找 4. 斐波那契查找 1. 线性查找 线性查找是逐一比对 ...
- 数据结构: 插值查找算法
import java.util.Arrays;// 插值查找算法,也要求数组是有序的 public class InsertValueSearch {public static void main( ...
- 大话数据结构:最短路径算法
dijkstra最短路径算法 迪杰斯特算法的核心是首先正向把离起点最近的点一个一个找出来,然后从终点开始逆向计算最短路径 利用图数据结构实现dijkstra算法的伪代码如下 {记录所有点到起点的距离并 ...
- 数据结构与算法---查找算法(Search Algorithm)
查找算法介绍 在java中,我们常用的查找有四种: 顺序(线性)查找 二分查找/折半查找 插值查找 斐波那契查找 1)线性查找算法 示例: 有一个数列: {1,8, 10, 89, 1000, 123 ...
- 数据结构之查找算法:基本概念
查找算法:基本概念 思维导图: 查找的基本概念及基本操作: 思维导图: 查找的基本概念及基本操作: ps: Pi表示元素出现的概率,一般情况下,默认各个元素出现的概率相同 Ci表示元素出现的次数
最新文章
- python递归题目_Python递归的问题?
- Thinking in java 多线程导致数组越界崩溃的BUG
- Qt+MinGW+OpenCV开发环境在win7系统下的搭建(最新20140423)
- 源码阅读之Java栈的实现
- xtrabackup增量备份mysql +MHA
- springboot 获取客户端ip_JAVA如何获取客户端IP地址和MAC地址
- disconf mysql_disconf-web 安装
- 怎么才能点一下excel中的超链接就显示出图片?_Excel如何批量建立超链接,搭建工作台...
- Phpcms V9全站伪静态设置方法
- hdu1247 字典树
- C语言实现base64编码,base64解码
- 基于python的学生信息管理系统
- Category 分类、类别 总结 - iOS
- libgdx 打飞机游戏实现教程
- 使用git push推送时出现错误error: failed to push some refs to ‘https://gitee.com/yang-yimu/vue_shop.git‘
- halcon机器视觉玩转车牌识别-超人视觉罗超
- JQuery对象与JavaScript对象的区别与转换
- 低功耗基础——Lib文件中对ICG的描述
- 中国未来最值得投资的十大行业
- Win10截图工具失效怎么办?这个方法帮你轻松修复
热门文章
- asp.net faq: 在html文件中,用js获取session
- android 带清除功能的输入框控件
- Binder ThreadPoolMax default = 15
- pytorch Dataset, DataLoader产生自定义的训练数据
- 张志华教授《机器学习导论》和《统计机器学习》课程讲义
- Selenium+java - 下拉框处理
- D. Imbalanced Array
- MongoDB作为windows服务来安装-2
- 记一次 javax.xml.soap.SOAPException:
- python3的print函数