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

● 代码,二分搜索

 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. Cygwin使用3-修改Cygwin的默认启动路径

    原先启动Cygwin后,pwd显示: C:\Documents and Settings\Administrator@IBM-EBDC0EAC4B7 ~$ pwdC:\Documents and Se ...

  2. inf 启动

    How to install an INF file using Delphi If you need to install an "inf" file using Delphi, ...

  3. Styles in Windows Phone

    1. Use resources in internal style file: <Application.Resources> <ResourceDictionary Source ...

  4. Hiero中versionscanner模块结构图

    花了两周读这个模块,终于把结构理清楚了,当然新功能也搞定了,搜索条件更宽松,可以找到binitem对象中更多的版本,截图如下: 当然功能也做出来啦: 代码如下: ################### ...

  5. codeblocks “can't find compiler executable in yourconfigured search ……”

    新安装的codeblocks 16.01,安装后打开提示如下,没法用..原因是编译器并没有找对自己安装的 mingw 的安装位置. 解决办法:如下图点击 Auto-detect 之后,会看到位置信息变 ...

  6. win7 上运行 php7 +

    win7 安装 php7+ 很简单, 这里不赘述 如何在phpstudy 添加   php7   百度也很容易找到. 但是在 php 7 运行的时候总是报0x0000007  或者 缺少 .dll 文 ...

  7. 自动化测试Java一:Selenium入门

    From: https://blog.csdn.net/u013258415/article/details/77750214 Selenium入门 欢迎阅读Selenium入门讲义,本讲义将会重点介 ...

  8. Android adb logcat输出日志显示不全解决方案

    在终端中使用adb logcat打印服务器json数据,如果返回数据过大超过4000字节(4K)即会截断不显示 原因:logcat在对于message的内存分配大概是4k左右.所以超过的内容都直接被丢 ...

  9. 理解Kubernetes(2): 应用的各种访问方式

    理解Kubernetes系列文章: 手工搭建环境 应用的各种访问方式 1. 通过 Pod 的 IP 地址访问应用 1.1 Pod 的IP地址 每个Pod 都会被分配一个IP地址,比如下面这儿pod的I ...

  10. Linux下静态库和动态库

    函数库分为静态库和动态库 动态库(格式为libname.so[.主版本号.次版本号.发行号]).在程序编译时并不会被链接到目标代码中,而是在程序运行时才被载入. 静态库是目标文件.a的归档文件(格式为 ...