▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法

● 代码,二分搜索

 package package01;

 import java.util.Arrays;
import edu.princeton.cs.algs4.StdRandom; public class class01
{
public int binarySearch(int [] a, int target) // 非递归实现
{
int lp = 0, rp = a.length - 1;
for(;lp <= rp;) // 含等号的条件,后面修改 lp 和 rp 是使用强的跳跃条件
{
int mp = lp + (rp - lp) / 2;
if (target < a[mp])
rp = mp - 1; // 不要使用 mp 作为跳跃条件,会导致死循环
else if (target > a[mp])
lp = mp + 1;
else
return mp;
}
return -1;
} public int binarySearchRecursion(int [] a, int target)// 递归实现
{
return binarySearchRecursionKernel(a,target,0,a.length-1);
} private int binarySearchRecursionKernel(int [] a, int target, int lp, int rp)
{
for(;lp<=rp;)
{
int mp = lp + (rp - lp) / 2;
if (target < a[mp])
return binarySearchRecursionKernel(a,target,lp,mp - 1);
else if (target > a[mp])
return binarySearchRecursionKernel(a,target,mp + 1, rp);
else
return mp;
}
return -1;
} public static void main(String[] args)
{
int N = 10000;
int [] a = new int [N];
for(int i=0;i<N;i++)
a[i] = i;//(int)(StdRandom.uniform()*10000); // 注释部分留作随机检验
//Arrays.sort(a); int target = 7919;//(int)(StdRandom.uniform()*10000);
int output1 = binarySearch(a,target);
int output2 = binarySearchRecursion(a,target); System.out.printf("\n%d,%d\n",output1,output2);
return;
}
}

● 重复元素二分搜索,包括查找第一次出现、最后一次出现,以及出现多少次

 package package01;

 import java.util.Arrays;
import edu.princeton.cs.algs4.StdRandom; public class class01
{
public int binarySearchFirst(int [] a, int target) // 寻找第一个等于键值的目标
{
return binarySearchFirstKernel(a, target, 0, a.length-1);
} private int binarySearchFirstKernel(int [] a, int target,int lp,int rp) // 添加起点和终点(两端点都包含),为了能与 Count 函数配合
{
for(;lp<=rp;)
{
int mp = lp + (rp - lp) / 2;
if (target < a[mp])
rp = mp - 1;
else if (target > a[mp])
lp = mp + 1;
else if(mp == 0 || target > a[mp-1]) // target == a[mp],找第一个
return mp; // a[mp] 就是第一个
else // a[mp] 前面还有等值的,不能强跳跃,否则可能跨空
rp = mp;
}
return -1;
} public int binarySearchLast(int [] a, int target) // 寻找最后一个等于键值的目标
{
return binarySearchLastKernel(a,target, 0, a.length-1);
} private int binarySearchLastKernel(int [] a, int target,int lp, int rp) // 添加起点和终点(两端点都包含)
{
for(;lp<=rp;)
{
int mp = lp + (rp - lp) / 2;
if (target < a[mp])
rp = mp - 1;
else if (target > a[mp])
lp = mp + 1;
else if(mp == a.length-1 || target < a[mp+1]) // target == a[mp],找最后一个
return mp; // a[mp] 就是第一个
else // a[mp] 后面还有等值的,不能强跳跃,否则可能跨空
lp = mp;
}
return -1;
} public int binarySearchCount(int [] a, int target) // 寻找等于键值的元素个数
{
int lp = 0, rp = a.length-1;
for(;lp<=rp;)
{
int mp = lp + (rp - lp) / 2;
if (target < a[mp])
rp = mp - 1;
else if (target > a[mp])
lp = mp + 1;
else // 找到元素后,搜查首个和最后一个进行计数
return binarySearchLastKernel(a,target,lp,rp) - binarySearchFirstKernel(a,target,lp,rp) + 1;
}
return -1;
} public static void main(String[] args)
{
int N = 10000;
int [] a = new int [N];
for(int i=0;i<N;i++)
a[i] = i/100;//(int)(StdRandom.uniform()*10000); // 用于随机测试
//Arrays.sort(a); int target = 29;//(int)(StdRandom.uniform()*10000); // 可以检验边界 0,99 等情况
int output1 = binarySearchFirst(a,target);
int output2 = binarySearchLast(a,target);
int output3 = binarySearchCount(a,target); System.out.printf("\n%d,%d,%d\n",output1,output2,output3);
return;
}
}

● 数组随机化

 package package01;

 public class class01
{
public static void shuffle(Object[] a)
{
int n = a.length;
for (int i = 0; i < n; i++)// 每次在 a[0] ~ a[i] 中随机挑一个 a[r],交换 a[i] 与a[r]
{
int r = (int)(Math.random() * (i + 1));
Object swap = a[r];
a[r] = a[i];
a[i] = swap;
}
} public static void shuffle2(Object[] a)
{
int n = a.length;
for (int i = 0; i < n; i++)// 每次在 a[i] 右边随机挑一个 a[r],交换 a[i] 与a[r]
{
int r = i + (int)(Math.random() * (n - i));
Object swap = a[r];
a[r] = a[i];
a[i] = swap;
}
} public static void main(String[] args)
{
String[] a = { "0","1","2","3","4","5","6","7","8","9" };
class01.shuffle(a);
for (int i = 0; i < a.length; i++)
System.out.print(a[i]); System.out.print("\n"); String[] b = { "0","1","2","3","4","5","6","7","8","9" };
class01.shuffle2(b);
for (int i = 0; i < a.length; i++)
System.out.print(b[i]); return;
}
}

● 计算图连通分量的算法。输入文件第一行是节点数,后面每行是一个连接的两端节点编号,用 java class01 < inputFile.txt 来运行。

 package package01;

 import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut; public class class01
{
private int[] parent; // 节点祖先标记
private int[] rank; // 树深度,仅根节点有效
private int count; // 节点数 public class01(int n)
{
count = n;
parent = new int[n];
rank = new int[n];
for (int i = 0; i < n; i++)
{
parent[i] = i;
rank[i] = 1; // 源代码用的是 0
}
} public int find(int p) // 寻找 p 的根标号
{
for (validate(p); p != parent[p]; p = parent[p]);
return p;
} public int count() // 节点数
{
return count;
} public boolean connected(int p, int q) // 判断 p 与 q 是否连通
{
return find(p) == find(q);
} public void union(int p, int q) // 合并 p 和 q
{
int rootP = find(p);
int rootQ = find(q);
if (rootP == rootQ)
return; if (rank[rootP] < rank[rootQ]) // 较小树连接到较大树的树根上,树高按最大值计算
parent[rootP] = rootQ;
else if (rank[rootP] > rank[rootQ])
parent[rootQ] = rootP;
else // 两树等大,合并后树高增一
{
parent[rootQ] = rootP;
rank[rootP]++;
}
count--; // 合并后连接分量减少
} public void union2(int p, int q) // 合并 p 和 q,第二种方法,更快
{
int rootP = find(p);
int rootQ = find(q);
if (rootP == rootQ)
return; if (rank[rootP] < rank[rootQ])
{
parent[rootP] = rootQ;
rank[rootQ] += rank[rootP]; // 树高按加和计算
}
else
{
parent[rootQ] = rootP;
rank[rootP] += rank[rootQ];
}
count--;
} private void validate(int p) // 判断输入的 p 是否合法
{
if (p < 0 || p >= parent.length)
throw new IllegalArgumentException("\np = " + p + "is illegal\n");
} public static void main(String[] args)
{
int n = StdIn.readInt();
class01 uf = new class01(n);
for (; !StdIn.isEmpty();)
{
int p = StdIn.readInt();
int q = StdIn.readInt();
if (uf.connected(p, q))
continue;
uf.union(p, q);
//StdOut.println(p + " " + q);
}
StdOut.println(uf.count() + " components");
}
}

《算法》第一章部分程序 part 1的更多相关文章

  1. 《算法》第一章部分程序 part 2

    ▶ 书中第一章部分程序,加上自己补充的代码,包括简单的计时器,链表背包迭代器,表达式计算相关 ● 简单的计时器,分别记录墙上时间和 CPU 时间. package package01; import ...

  2. C语言编程入门之--第一章初识程序

    第一章 初识程序 导读:计算机程序无时不刻的影响着人类的生活,现代社会已经离不开程序,程序的作用如此巨大,那么程序到底是什么呢?本章主要讨论程序的概念,唤起读者对程序的兴趣,同时对C语言程序与其它语言 ...

  3. windows核心编程-第一章 对程序错误的处理

    第一章-对程序错误的处理 在开始介绍Microsoft Windows 的特性之前,必须首先了解 Wi n d o w s的各个函数是如何进行错误处理的. 当调用一个Wi n d o w s函数时,它 ...

  4. 第一章 Python程序语言简介

    第一节 Python概述 1. 什么是Python Python是一种 解释型.面向对象.动态数据类型 的高级程序设计语言.由Guido van Rossum与1989年发明,第一个公开发行版本发行于 ...

  5. ASP.NET本质论第一章网站应用程序学习笔记3-对象化的Http

    在.NET环境下,万物皆对象,在HttpRuntime收到请求之后,立即将通过HttpWorkerRequest传递的参数进行分析和分解,创建方便用于网站应用程序处理用的对象,其中主要涉及到两个对象类 ...

  6. ASP.NET本质论第一章网站应用程序学习笔记2

    1.初步走进ASP.NET 上篇笔记我们讲述了服务器监听问题,这篇我们就要讲述具体的请求处理了,ASP.NET所涉及的类大多数定义在System.Web程序集中. 在.NET中,程序集管理的最小逻辑单 ...

  7. ASP.NET本质论第一章网站应用程序学习笔记1

    1.统一资源标示符 1) 格式:协议://主机[.端口号][绝对路径[?参数]],在Http://www.kencery.com/hyl/index/login中,http表示协议的名称,www.ke ...

  8. 《程序是怎样跑起来的》读书笔记——第一章 对程序员来说CPU是什么

    1 程序的运行流程 2 CPU的组成 3 寄存器的主要种类和功能 "程序计数器"--决定程序流程的 4 条件分支和循环机制 4.1 顺序执行 4.2 选择分支 5 函数的调用机制 ...

  9. 【学习总结】java数据结构和算法-第一章-内容介绍和授课方式

    总目录链接 [学习总结]尚硅谷2019java数据结构和算法 github:javaDSA 目录 几个经典算法面试题 算法和数据结构的重要性 几个经典算法面试题 字符串匹配 暴力法:慢 kmp算法:更 ...

随机推荐

  1. 关于class produre

    很好理解 type TMessageHandler = class //使得回车消息转换成Tab消息 class procedure AppMessage(var Msg:TMsg;var Handl ...

  2. js图片预加载后触发操作

    为了使得图片加载完,再触发回调函数,需进行图片预加载处理 function loadImage(url, callback) { var img = new Image(); img.src = ur ...

  3. 【巷子】---react-redux---【react】

    一.Redux与组件 react-redux是一个第三方插件使我们在react上更方便的来使用redux这个数据架构 React-Redux提供connect方法,用于从UI组件生成容器组件,conn ...

  4. NPC问题及证明

    致谢:http://www.docin.com/p-1902790324.html

  5. T-SQL select语句连接两个表

    当一个表中按条件出现多个记录时,会按照匹配条件生成多个结果记录.left out 和right out 是对不能匹配的记录发生作用.

  6. STL基础--容器

    容器种类 序列容器(数组,链表) Vector, deque, list, forward list, array 关联容器(二叉树),总是有序的 set, multiset根据值排序,元素值不能修改 ...

  7. Ubuntu 14.10 下安装rabbitvcs-版本控制

    在Windows下用惯了TortoiseSVN这只小乌龟,到了Ubuntu下很不习惯命令行的SVN,于是经过一番寻找安装了RabbitVCS这款SVN图形化前端工具(官方网站:http://rabbi ...

  8. vue之v-for

    vue.js 的循环渲染是依赖于 v-for 指令,它能够根据 vue 的实例里面的信息,循环遍历所需数据,然后渲染出相应的内容.它可以遍历数组类型以及对象类型的数据,js 里面的数组本身实质上也是对 ...

  9. tcpdump命令(转载)

    https://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.html 简介 用简单的话来定义tcpdump,就是:dump the tra ...

  10. [UE4]GameMode、GameInstance、GameState、PlayerState、PlayerController

    一.只有PlayerController和Pawn/Character才有输入事件(键盘.鼠标等等),PlayerState没有输入事件. 二.对于需要跨域关卡的数据信息,根据上图所知需要放到Game ...