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

● 代码,二分搜索

 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. xe5 android sample 中的 SimpleList 是怎样绑定的 [转]

    C:\Users\Public\Documents\RAD Studio\12.0\Samples\FireMonkeyMobile 例子中的绑定方式如下图: 1.拖拽一个listview到界面上,然 ...

  2. UML类图快速入门篇

    1.关联 1.1双向关联: C1-C2:指双方都知道对方的存在,都可以调用对方的公共属性和方法. 在GOF的设计模式书上是这样描述的:虽然在分析阶段这种关系是适用的,但我们觉得它对于描述设计模式内的类 ...

  3. 【剑指offer】逆序输出链表

    输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. *考察栈的使用 *使用循环输出Stack中内容的时候,不能使用for(int i; i<stack.size();i++)因为s ...

  4. C/C++程序CPU问题分析

    转载地址:http://www.10tiao.com/html/473/201606/2651473094/1.html   程序的CPU问题是另外一类典型的程序性能问题,很多开发人员都受到过程序CP ...

  5. 科学-天文学-天文观测站:TMT(红外天文望远镜)

    ylbtech-科学-天文学-天文观测站:TMT(红外天文望远镜) 30米望远镜(Thirty Meter Telescope,TMT) 系由美国加州大学和加州理工学院负责研制的新一代地基巨型光学-红 ...

  6. 云区域(region),可用区(AZ),跨区域数据复制(Cross-region replication)与灾备(Disaster Recovery)(部分1)

    本文分两部分:部分1 和 部分2.部分1 介绍 AWS,部分2 介绍阿里云和OpenStack云. 1. AWS 1.1 AWS 地理组件概况 AWS 提供三种地理性组件: Regions:区域,即A ...

  7. Java中涉及线程和并发相关的内容

    1:线程池 与每次需要时都创建线程相比,线程池可以降低创建线程的开销,这也是因为线程池在线程执行结束后进行的是回收操作,而不是真正的 销毁线程. 2:ReentrantLock ReentrantLo ...

  8. Android接听、挂断电话

    新建一个名为ITelephony的aidl文件,注意包名不能改变,因为是通过反射方式来实现接听和挂断的

  9. css3凹角效果

    <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Conten ...

  10. visual studio 版本管理从tfs迁移到svn

    1.首先要解除解决方案的tfs绑定 清除(删除)项目下的所有版本控制文件,这些文件有:*.vssscc,*.vspscc 删除这些版本控制文件比较简单,搜索这些后缀的文件,删除即可. 修改项目的解决方 ...