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

● 代码,二分搜索

 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. WebService安全性的几种实现方法【身份识别】

     转:http://blog.csdn.net/yongping8204/article/details/8619577 WebService安全性的几种实现方法[身份识别] 标签: webservi ...

  3. Configure Virtual Serial Port Driver (vspd)注册表

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VSBC7\Ports\COM3COM4] “Port1”=”COM3” “Port2”=” ...

  4. 黄聪:PHP代码获取客户端IP地址经纬度及所在城市

    echo $_SERVER['HTTP_HOST']; //echo $_SERVER['REQUEST_URI']; $getIp=$_SERVER["REMOTE_ADDR"] ...

  5. Node.js 0.12: 正确发送HTTP POST请求

    Node.js 0.12: 正确发送HTTP POST请求 本文针对版本:Node.js 0.12.4 之前写过一篇Node.js发送和接收HTTP的GET请求的文章,今天再写一篇,讲发送POST的请 ...

  6. 【RPC】使用Hessian构建RPC的简单示例

    服务接口和实现 public interface HelloService { // 服务方法 String sayHello(String name); } public class HelloSe ...

  7. bzoj5010: [Fjoi2017]矩阵填数

    Description 给定一个 h*w 的矩阵,矩阵的行编号从上到下依次为 1..h,列编号从左到右依次1..w.在这个矩阵中你需要在每 个格子中填入 1..m 中的某个数.给这个矩阵填数的时候有一 ...

  8. 云中树莓派(5):利用 AWS IoT Greengrass 进行 IoT 边缘计算

    云中树莓派(1):环境准备 云中树莓派(2):将传感器数据上传到AWS IoT 并利用Kibana进行展示 云中树莓派(3):通过 AWS IoT 控制树莓派上的Led 云中树莓派(4):利用声音传感 ...

  9. 计划任务at、crontab

    at一次性计划任务 格式: at + 时间 命令 安装at # yum install at -y 如果执行at命令时,出现一下情况 Can't open /var/run/atd.pid to si ...

  10. USACO 2008 Running(贝茜的晨练)

    [题解] 动态规划,dp[i][j]表示第i分钟疲劳度为j的最长距离. [代码] #include <iostream> #include <cstdlib> #include ...