5-26题记

1464277362

问题描述

小明正在玩一个“翻硬币”的游戏。

桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。

比如,可能情形是:oo*oooo

如果同时翻转左边的两个硬币,则变为:oooo***oooo

现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?

我们约定:把翻动相邻的两个硬币叫做一步操作,那么要求:

输入格式

两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000

输出格式

一个整数,表示最小操作步数。
样例输入1


oo

样例输出1

5

样例输入2

o*oo
o**oo*

样例输出2

1

代码实现

import java.util.Scanner;

/**

  • 翻硬币

  • @author Ape

  • /
    public class Fanyb {

    static int[] hash = new int[1001];
    static String s1, s2;
    static int vis = -1, ans = 0;

    public static void main(String[] args) {

    Scanner scanner = new Scanner(System.in);
    s1 = scanner.nextLine();
    s2 = scanner.nextLine();
    for (int i = 0; i < s1.length(); i++)
        if (s1.charAt(i) == s2.charAt(i))
            hash[i] = 0;
        else
            hash[i] = 1;
    for (int i = 0; i < s1.length(); i++)
        if (hash[i] == 1) { // 检测到不相同
            if (vis == -1) // 如果前面没有记录的1的下标,记录当前1的下标
                vis = i;
            else {
                ans += i - vis;
                vis = -1;
            }
        }
    System.out.println(ans);
    scanner.close();

    }

}

问题描述

给定N个物品,每个物品有一个重量W和一个价值V.你有一个能装M重量的背包.问怎么装使得所装价值最大.每个物品只有一个.
输入格式

输入的第一行包含两个整数n, m,分别表示物品的个数和背包能装重量。

以后N行每行两个数Wi和Vi,表示物品的重量和价值
输出格式

输出1行,包含一个整数,表示最大价值。
样例输入

3 5
2 3
3 5
4 7

样例输出

8

数据规模和约定

1<=N<=200,M<=5000.
代码实现

import java.util.Scanner;

/**

  • @author Ape

  • /
    public class DpBeiBao {

    static int[] w = new int[201]; // 物品重量
    static int[] p = new int[201]; // 物品价值
    static int n, W; // W背包重量

    public static void main(String[] args) {

    Scanner scanner = new Scanner(System.in);
    n = scanner.nextInt();
    W = scanner.nextInt();
    for (int i = 0; i < n; i++) {
        w[i] = scanner.nextInt();
        p[i] = scanner.nextInt();
    }
    int[] b = new int[W + 1]; // 数组下标为背包的重量,值为当前重量的价值
    for (int i = 0; i < w.length; i++)
        for (int j = W; j >= w[i]; j--) // 以不超过背包最大重量前提计算物品最大值
            if (b[j - w[i]] + p[i] > b[j])
                b[j] = b[j - w[i]] + p[i];
    System.out.println(b[W]);
    scanner.close();

    }

}

ps:距离比赛还有一天,哈哈,北京我来了

5-27题记

1464303700

昨晚1点半才睡,为的是这两题,今早6点起来现在已经整顿好淡定的发博客

一题是省赛压轴题,为何我一看代码思路全明了捏,当时想死都想不出

题目描述

密码脱落

X星球的考古学家发现了一批古代留下来的密码。

这些密码是由A、B、C、D 四种植物的种子串成的序列。

仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的镜像串)。

由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征。

你的任务是:

给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子。

输入一行,表示现在看到的密码串(长度不大于1000)

要求输出一个正整数,表示至少脱落了多少个种子。

例如,输入:

ABCBA

则程序应该输出:

0

再例如,输入:

ABECDCBABC

则程序应该输出:

3

资源约定:

峰值内存消耗(含虚拟机) < 256M

CPU消耗 < 3000ms
代码实现

import java.util.Scanner;

/**

  • @author Ape

  • /
    public class A10 {

    static char[] s = new char[1000];
    static int min = 0, num = 0;

    static void fcode(int left, int right, int num) {

    if (left >= right) {
        min = min < num ? min : num;
    } else {
        if (s[left] == s[right]) {
            fcode(left + 1, right - 1, num);
        } else {
            fcode(left + 1, right, num + 1);
            fcode(left, right - 1, num + 1);
        }
    }
    return;

    }

    public static void main(String[] args) {

    // TODO Auto-generated method stub
    Scanner scanner = new Scanner(System.in);
    String str = scanner.nextLine();
    s = str.toCharArray();
    min = s.length;
    fcode(0, min - 1, 0);
    System.out.println(min);
    scanner.close();

    }

}

题目占时找不到了,看代码可以找到什么意思,准备出发

import java.util.Scanner;

public class DpShop {
static final int MAX = 10001;
static int[] p = new int[MAX];
static int[] w = new int[MAX];
static int W, n, ans = 0;

static void dfs(int value, int vn) {
    if (n == vn)
        return;
    if (value > 1000)
        return;
    if (value == 1000) {
        ans++;
        for (int i = 0; i < n; i++)
            System.out.print(w[i] + " ");
        System.out.println();
    } else {
        dfs(value, vn + 1);
        if (value + p[vn] <= 1000) {
            w[vn]++;
            dfs(value + p[vn], vn);
            w[vn]--;
        }
    }
}

static void f(int total, int size) {
    if (size != n) {
        if (total == 0)// 判断背包是否正装满
        {
            ans++;// 存放可行方案的个数
            for (int i = 0; i < n; i++)
                System.out.print(w[i] + " ");
            System.out.println();
        } else {
            f(total, size + 1);// 未放入物品a【size】的情况
            if (total - p[size] >= 0)// 判断放入a【size】后,是否会超出背包的承载
            {
                w[size]++;// 使得a【size】对应物品的数量加1
                f(total - p[size], size);// 放入物品a[size]的情况
                w[size]--;// 使得相应的物品数量减1
            }
        }
    }
}

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    n = scanner.nextInt();
    for (int i = 0; i < n; i++)
        p[i] = scanner.nextInt();
    // f(1000, 0);
    dfs(0, 0);
    scanner.close();
}

}

北京之旅

1464877342

4天的北京历程结束了,比赛也结束了,全国总决赛二等奖,收获的不仅仅是名次,这几天对北京的印象,菜式风味,各种重口味,老北京话,还有北京烤鸭,去了清华北大北科天安门故宫…
谈比赛

说到比赛,其实去到现场没有想象中的那种感觉,没有上次去珠海比赛的那种感觉,也许是我把这个全国总决赛想得太重大,其实没有什么,但对有些人来说确实是,对别人却当平常一样。我们一行人四个都是在北科考点,经历了之前那么多,加上都来了北京参加总决赛,对我而言结果已经没有那么重要了,全力以赴就好,当时就想着比完赛要去哪里哪里玩,心平气和的心态进入考场。

毕竟全国总决赛,进考场的时候还好,起码没有省赛那么假,但是始终没有那次职业技能大赛那样,让我感觉到高考的氛围,而且那时候再加上导师的关系与照顾。坐我隔壁的是南京工业职业技术学院的,也是大二,他是C\C++组的,叫张威,一听名字让我想到最强大脑里边那个李威,都是非常厉害的人,当时我们还互相留了QQ号,再过去一位是甘肃的,隔得太远只是轻聊了几句。

比赛开始了,解压了文件夹马上打开题目作答,第一道题我Java组跟C++组是一样的题,看完题目我看到隔离的马上打开Excel表格,哇,看到这一幕,我是发自内心的称赞,屌!厉害厉害非常厉害,然后我也马上敲代码,题目大意是求平方数的后两位有多少种可能,思路是用一个长度100的一位数组对平方数取模100,进行hash标记,答案是22,我比他快一步算出来。果然,总决赛的题目还是有点难度的,思路是有的,大多都用深度优先,需要专注耐心,因为数据量大,一个变量错了就得不到结果,后边考我听他们说用了14重for循环,我天,也是可以的哈哈这个更需要耐心写。接下来的第四第五题我都是直接给他套深度优先,第五题题目意思差点没理解,看了好一会才知道是什么意思,看来语文水平有待提高,前面5题全部做完了剩最后一题,我不知道这道题考的是语文还是算法,我看了十几二十分钟竟没理解什么意思,115分的题目我竟跟它插件而过总分300,无奈只好去检查前面5题,白检查了,又重算了一遍都一样,筛我时间,直到比赛结束最后一题我还是没有提交,原则是不算出来不提交答案,无望了。最后我还是有点后悔没提交答案,随缘。
谈旅程

这是我第二次做的动车,10点的车,我们一大早8点多就去到那里干等着,也表现出了我们无比激动的心情。由于种种原因,我跟他们座位离了好远。

找到我的座位发现是一个小女孩坐着,然后她妈妈问我是这个座位的吧要求我换一下座位要照看小孩,我就笑着说可以呀没问题。就这样我跟一对50多岁的叔叔阿姨还有一个小孩坐在一起,那阿姨很热情他们两口子跟我聊天聊了好久还给我吃的,老家是韶关的,现在住佛山,叔叔说他16岁就去当兵,一名军人来的,才得知他们是一家子,是一个家族的人20多个,要去北京喝喜酒。在这个车厢里边都是去北京的,应该有三分之一是去参加蓝桥杯比赛的吧,历程8小时的车,没有玩手机,只有聊天发呆睡觉。

下了动车坐地铁,发现北京的地铁没有广州设计得好,但是他的地铁票比广州的好,广州的是一枚绿色的币北京的是一张卡,cool!去到酒店,发现又跟想象中的不一样,住的是四环。

任性的我们来到北京出门基本都是直接打的,四个人不多不少,玩得太嗨,已失忆。。。。

返程的时候我又是隔离开了,跟一位刚跟女儿玩回来广州大学的老师,和一位刚带完学生比赛的武汉大学老师,一位是教电子通讯,一位是C++,跟我专业相似的。当时是我先开口问的,因为我看到他旅行袋上面写着云计算,之后三个聊在了一起可嗨了,后来就睡着了,可能是玩得太累了,那老师下车的时候还跟我说,小伙子前途无量呀。其实有时候觉得做火车动车什么的可以接触社会各类各界的人,有点意思。
谈北京

北京,中国的首都,听起来很是高大上,但还是跟想象中的差那么一点点,所以说遐想是最美好的,去了反而毁了你的遐想,但是不去又是一种遗憾哈哈。北京人北京话北京菜北京烤鸭北京印象,也算是见了地方人听了地方话尝了地方菜。北京人很随和,热情,在北京几天我没有听到过一句粗口话,(也许他们说了我也听不懂),北京话腔调很重,说完我还有愣一下才反应过来,但是说得还是比较标准的,起码比我好,北京菜我是真的吃不惯,就当尝了一回北京特色吧,什么乾隆白菜都是重口味很甜的,感觉都是在吃配料,原味都没有了。北京烤鸭108片片片带皮这是真的,但是有些根本就不带肉,算了算了反正我是吃到了传说中的北京烤鸭。
低调晒两张图

Editplus一键格式化代码

1464780511

喜欢用Editplus的朋友可以来看看,你没有用过也没关系,如果你有兴趣可以下载来用用,我个人是很推荐使用,可以进入http://desktop.xiaocp.com/下载

用过Editplus的人都知道,他没有自带的一键格式化代码功能,有时候会很烦,

下面两步实现Editplus一键格式化代码
1、先下载需要的文件

edtools.rar

解压后放到磁盘的一个目录,如D:/plus
2、打开Editplus

打开“工具”-“用户工具组”,在弹出的对象框中,在“组和工具项目”下拉框中选择一个工具组,点击“组名称”,为该组工具设定一个名称,如“前端开发工具”

点击“添加”–“应用程序”,在新建的项中,菜单文本写上名称,如”jsFormat”,在命令里面输入:

Java代码

cscript /nologo ”D:\edTools\jsFormatter.js”

后面引号中的内容要修改你磁盘上对应的文件的路径。

“动作”选择“运行为文本过滤器(替换)”

“保存”选为“无”

如下图所示:

其它几个的安装方式与htmlFormat的安装类似,这里不再重复。
接下来是见证奇迹的时刻,按下Ctrl + 1

duang~是不是特技出来了

带www与不带www的互相跳转

1466087447

相信大家平常时浏览网页已经发现了,有些网站是没有www开头的直接是一个一级域名,下面介绍如何在网站加上www如何去掉www,仅支持iis服务,与Apache服务,跳转的规则代码如下
带www跳转到不带www:

RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]

不带www跳转到www:

RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www..+$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

将上面代码加入.htaccess文件即可,不需要修改什么。所以只需要新建一个文件之后利用URL重写导入规则就好了。

有时候也想自己一个人静一静

有时候也想自己一个人静一静

1466812966

前言:现在的社会显得很浮躁,我们的大部分时间被手机、朋友圈给占据了,我们忙于应付各种各样的社交,但是却很少去思考这样的社交是不是有价值的。其实,这些成本低却意义不高的社交,反而不如自己用心独处去做一些有意思的事情呢~

谈谈我,一个不上微信不刷朋友圈不刷微博的我,成天到晚基本不玩手机的人,可能是因为我的iphone是2G网络的原因吧,也许是手机对我来说已经失去了意义。

低品质的社交应该很多人都有过,比如社交对象的质量不到位,就不能收获一次高质量的谈话。你谈天说地,他歌舞升平,你谈的是对生命的思考,他跟你讲的是:哥们,再喝一个。

人们之间的交往,你要学会在接触之后对他们进行质量的评估,很多人和你不过是点头之交,喝茶、打牌、唱歌、喝酒,然后彼此说些不过脑袋的话,你以为你收获了快乐,其实你只是又糊里糊涂的过了一天。

应该有很多的人认为认识的人越多越好,多一个朋友多一条路,但是人与人之间的交往是得你来我往,长时间的交互才会形成坚固的友谊,这个时候才能称为朋友,其实你和很多你自以为的朋友不过是吃了几顿饭,喝了几顿酒,这样的朋友我相信是打引号的。

朋友圈之前有一个游戏:如果我无家可归了,有谁会收留我。你觉得这些酒肉朋友会毫不犹豫地接纳你吗?你和他们的关系永远是站在利益之上的。

人和人之间的交往很多时候是建立在价值之上,你的价值越高,当然身边围绕的“朋友”越多,那假如有一个你的价值消失,比如你公司破产,你官位不保等等,这些“朋友”还围着你转吗?那你为什么把那么多时间花在这些人身上?

真正的朋友是用心交的,当然还要加上时间,因为日久见人心。

你每天花大量的时候在各种微信群当中活跃着,翻看着一条条的聊天记录,你去参加某个聚会,最后发现狂欢是一群人的孤单,聚会结束,留下的是空虚寂寞冷。你无休止地想要讨好某人,而别人只在你送上“礼物”送上金币的时候才正眼瞧你。

这些低质量的社交,不去为好。

小时候我一直很羡慕那些穿梭于灯红酒绿的人。而后来我也穿梭于灯红酒绿的时候我发现每天我会认识很多人,都是陌生的面孔,我们称兄道弟,几杯酒下肚就学着刘关张桃园结义。而第二天酒醒之后我甚至连那人的联系方式都没有,甚至已经记不清他是什么模样。

第二次见到这个人,我们彼此顿个几秒钟,感觉好像在哪见过,于是喊着兄弟,你是那个什么是吧?然后继续喝酒,然后喝醉,第二天继续不知道谁是谁。

也许有些你留下了联系方式,那你有拨通过一次吗?当你真的遇到困难,需要借钱需要帮忙的时候,你会首先想到这些人吗?

与其每天东奔西走,进行低质量的社交,还不如一个人静静的待着。

喂马,劈柴,周游世界。

面朝大海,春暖花开。

当然在城市里,我们没有那么多诗和远方去感受,但你可以发呆,看书,听音乐。

你可以健身,看电影,骑行。

一个人该怎么高质量的独处因人而异,最重要的是看你自己想做什么,做自己最喜欢的事,爱自己最爱的人。

你要相信,一个真正成功的人一定是学会了独处的人,首先要保持内心的平静才能够冷静的思考,你总是说身边的一切太浮躁了,那么你就试着远离那些不好的人或者地点。

有一天你会明白,你会想去和更优秀的人聊天,他们不会带你去酒吧,也许只是陪你河边走走。你能从他们那里学习和领悟一些东西,这才是高质量的。

社交并不光指认识很多人,而是充满选择性的,之前看过一篇文章,说为什么优秀的人不会帮你,是因为这些比你优秀的人明白一个道理,跟你的社交对他们来说是低质量的,有素质一点的会敷衍你,绝情一点的会对你闭门不见。

低质量的社交,不如高质量的独处。

作者何善尼

漫谈设计模式之观察者模式

1468149247

观察者模式定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

打个比方,就拿梦幻西游战斗中轮流出招来说,三个人物,龙太子,剑侠客,逍遥生,先是龙太子出招,他先作为事件的发生者,然后其他两个人物作为观察者剑侠客,逍遥生的游戏界面就会更新着画面显示龙太子出招。

观察者接口实现

<?php
/**

  • Created by PhpStorm.
  • User: Ape
  • Date: 2016-7-10
  • Time: 14:39
  • /

namespace Open\Observer;

/**

  • 所有观察者必需实现此接口

  • Interface Observer

  • @package Open\Observer

  • /
    interface Observer
    {
    /**

    • 观察者更新方法

    • @param null $msg

    • @return mixed

    • /
      function update($msg = null);
      }

      事件源基类的实现

<?php
/**

  • Created by PhpStorm.
  • User: Ape
  • Date: 2016-7-10
  • Time: 14:51
  • /

namespace Open\Observer;

abstract class Event
{
/**
* 这里设置为private,事件发生者不用关心
* @var array
*/
private $observers = array();

/**
 * 添加观察者
 * @param Observer $observer
 */
function addObserver(Observer $observer){
    $this->observers[] = $observer;
}

/**
 * 移除观察者
 * @param Observer $observer
 */
function removeObserver(Observer $observer){
    foreach($this->observers as $k => $value)
        if($observer === $value)
            unset($this->observers[$k]);
}

/**
 * 通知所有观察者更新
 * @param null $msg
 */
function notify($msg = null){
    foreach($this->observers as $observer)
        $observer->update($msg);
}

}

龙太子

<?php
/**

  • Created by PhpStorm.
  • User: Ape
  • Date: 2016-7-10
  • Time: 15:07
  • /

namespace Open\Observer;

class Event1 extends Event implements Observer
{
public $name = ‘龙太子’;

public function trigger(){
    $m = $this->name.':我使出龙腾<br/>';
    echo $m;
    $this->notify($this->name.'使出龙腾<br/>');
}

public function update($msg = null){
    echo $this->name.'看到'.$msg.'<br/>';
}

}

剑侠客

<?php
/**

  • Created by PhpStorm.
  • User: Ape
  • Date: 2016-7-10
  • Time: 15:07
  • /

namespace Open\Observer;

class Event2 extends Event implements Observer
{
public $name = ‘剑侠客’;

public function trigger(){
    $m = $this->name.':我使出横扫千军<br/>';
    echo $m;
    $this->notify($this->name.'使出横扫千军<br/>');
}

public function update($msg = null){
    echo $this->name.'看到'.$msg.'<br/>';
}

}

逍遥生

<?php
/**

  • Created by PhpStorm.
  • User: Ape
  • Date: 2016-7-10
  • Time: 15:07
  • /

namespace Open\Observer;

class Event3 extends Event implements Observer
{
public $name = ‘逍遥生’;

public function trigger(){
    $m = $this->name.':我使出牛刀小试<br/>';
    echo $m;
    $this->notify($this->name.'使出牛刀小试<br/>');
}

public function update($msg = null){
    echo $this->name.'看到'.$msg.'<br/>';
}

}

注:以上三个类既作为事件发生者也作为观察者
测试代码

<?php
$event1 = new Open\Observer\Event1();
$event2 = new Open\Observer\Event2();
$event3 = new Open\Observer\Event3();

$event1->addObserver($event2);
$event1->addObserver($event3);
echo “现在是 $event1->name 出招
“;
$event1->trigger();

$event2->addObserver($event1);
$event2->addObserver($event3);
echo “现在是 $event2->name 出招
“;
$event2->trigger();

$event3->addObserver($event1);
$event3->addObserver($event2);
echo “现在是 $event3->name 出招
“;
$event3->trigger();

结果输出

现在是 龙太子 出招
龙太子:我使出龙腾
剑侠客看到龙太子使出龙腾
逍遥生看到龙太子使出龙腾

现在是 剑侠客 出招
剑侠客:我使出横扫千军
龙太子看到剑侠客使出横扫千军
逍遥生看到剑侠客使出横扫千军

现在是 逍遥生 出招
逍遥生:我使出牛刀小试
龙太子看到逍遥生使出牛刀小试
剑侠客看到逍遥生使出牛刀小试

漫谈设计模式之代理模式实现数据库读写分离

1468210803

一个大型网站,一般都是有人多个数据库服务器,实现主从同步读写分离,那么现在就简单的演示一下使用代理模式实现数据库读写分离。代理模式就相当于一个中介。关于主从数据库配置文章链接http://xiaocp.com/single/66

下面先是一个工厂类

<?php
/**

  • Created by PhpStorm.
  • User: Ape
  • Date: 2016-7-8
  • Time: 01:29
  • /

namespace Open;
use Open\Adapter\MySql;

/**

  • 工厂模式

  • Class Factory

  • @package Open

  • /
    class Factory
    {
    // 主库配置信息,当然这里是为了方便演示,一般把配置数据放到配置文件中
    static $master = array(

    'host' => '1.1.1.1',
    'username' => 'root',
    'password' => 'root',
    'db' => 'test'

    );
    // 从库配置信息
    static $slave = array(

    array(
        'host' => '2.2.2.2',
        'username' => 'root',
        'password' => 'root',
        'db' => 'test'
    ),
    array(
        'host' => '3.3.3.3',
        'username' => 'root',
        'password' => 'root',
        'db' => 'test'
    )

    );

    static function createDatebase(){

    $db = Database::getInstance();
    return $db;

    }

    /**

    • 数据库选择
    • @param string $id
    • @return MySql
    • /
      static function getDatabase($id = ‘’){
      if($id == ‘master’)
      $conf = self::$master;
      else
      $conf = array_rand(self::$slave);
      $db = new MySql($conf[‘host’], $conf[‘username’], $conf[‘password’], $conf[‘db’]);
      //TODO 这里可以使用注册树模式进行键值对的存取,避免重新创建
      return $db;
      }

}

代理类

<?php
namespace Open\Proxy;
/**

  • Created by PhpStorm.
  • User: Ape
  • Date: 2016-7-11
  • Time: 00:33
  • /
    class Proxy
    {
    // 代理方法进行判断当前的操作,从而选择对应的库操作
    function query($sql){
    if(substr($sql, 0, 6) == 'select'){
        echo "当前slave进行读操作:{$sql}<br>";
        \Open\Factory::getDatabase('slave')->query($sql);
    }else{
        echo "当前master进行写操作:{$sql}<br>";
        \Open\Factory::getDatabase('master')->query($sql);
    }
    }
    }

测试

<?php
$p = new \Open\Proxy\Proxy();
$p->query(‘select * from ape’);
$p->query(‘update ape set name = jw where id = 1’);

那么现在我们已经简单的实现了数据库读写分离.

运行结果

当前slave进行读操作:select * from ape
当前master进行写操作:update ape set name = jw where id = 1

排序算法之堆排序

1468449529

讲真,我是因为数据结构考试看了一下复习资料才知道的堆排序,一学期没上课的后果。于是,查了资料了解了这一算法。

俗话说堆栈堆栈,堆跟栈是什么就不说了。堆可以被看成是一棵树,那么就有了二叉堆,最小堆最大堆的说法。以下是百度百科的对堆的简述

堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。

最大堆和最小堆是二叉堆的两种形式。

最大堆:根结点的键值是所有堆结点键值中最大者。

最小堆:根结点的键值是所有堆结点键值中最小者。

而最大-最小堆集结了最大堆和最小堆的优点,这也是其名字的由来。

最大-最小堆是最大层和最小层交替出现的二叉树,即最大层结点的儿子属于最小层,最小层结点的儿子属于最大层。

以最大(小)层结点为根结点的子树保有最大(小)堆性质:根结点的键值为该子树结点键值中最大(小)项。
如图所示

堆的存储如下图所示

那么很容易看出第n个结点的父结点下标就为(n – 1) / 2。它的左右子结点下标分别为2 * n + 1 和 2 * n + 2。如第0个结点左右子结点下标分别为1和2。
代码实现

package com.w.sort;

public class Dsort {

static int[] array = new int[] { 15, 21, 6, 30, 23, 66, 20, 17 };

/**
 * 生成最小堆,最小堆的任意子树根节点不大于任意子结点
 * 
 * @param array
 * @param heapSize
 *            堆的大小
 * @param parent
 *            父节点下标索引
 */
static void minHeap(int[] array, int heapSize, int parent) {
    int left = parent * 2 + 1; // 左孩子
    int right = parent * 2 + 2;// 右孩子
    if (left < heapSize && array[left] > array[parent]) { // 判断孩子是否大于父节点的值,大于则交换,并继续找当前节点的子节点进行判断
        swap(array, left, parent);
        minHeap(array, heapSize, left);
    }
    if (right < heapSize && array[right] > array[parent]) {// 同上
        swap(array, right, parent);
        minHeap(array, heapSize, right);
    }
}

static void swap(int[] array, int x, int y) {
    int t = array[x];
    array[x] = array[y];
    array[y] = t;
}

public static void main(String[] args) {
    // TODO Auto-generated method stub
    int length = array.length;
    // 初始化为最小堆
    for (int i = length / 2; i >= 0; i--)
        minHeap(array, length - 1, i);

    for (int i = length - 1; i >= 1; i--) {
        swap(array, 0, i); // 每次将最小的数array[0]换到后面有序区间
        minHeap(array, i, 0);
    }

    for (int i = 0; i < length; i++)
        System.out.print(array[i] + " ");
}

}

排序算法之归并排序

1468669076

这次带来的是归并排序算法,怪我以前无知,只会了快排,冒泡,选择,插入等,也是没听数据结构课的后果,看了下书查了资料对归并排序有了深入了理解,归并归并,先递归后合并,先来张图看看你就理解了,如图

看完是不是感觉归并排序很简单拉哈,思路大概是这样:每次对半分组分组,分到每个1组然后进行比较大小合并数组

Java代码实现如下:

/**

  • 归并排序

  • @author Ape

  • /
    public class Gsort {

    static int[] array = new int[] { 1, 80, 116, 165, 20, 51 };

    // 将有二个有序数列合并
    static void mArray(int[] a, int[] t, int start, int mid, int end) {

    // s1-e1为第一段,s2-e2为第二段
    int s1 = start, e1 = mid , s2 = mid + 1, e2 = end;
    int n = 0;
    // 从每组的第一个数开始判断
    while (s1 <= e1 && s2 <= e2) {
        if (a[s1] <= a[s2])  // 若第一个组的数小
            t[n++] = a[s1++];
        else
            t[n++] = a[s2++];
    }
    // 把剩下的数拼上去
    while (s1 <= e1)
        t[n++] = a[s1++];
    while (s2 <= e2)
        t[n++] = a[s2++];
    for (int i = 0; i < n; i++)
        a[start + i] = t[i];

    }

    static void sort(int a[], int[] t, int start, int end) {

    if (start < end) {
        // 每次对半分
        int mid = (start + end) / 2;
        sort(a, t, start, mid);
        sort(a, t, mid + 1, end);
        mArray(a, t, start, mid, end);
    }

    }

    public static void main(String[] args) {

    // TODO Auto-generated method stub
    int length = array.length;
    int[] t = new int[length];
    sort(array, t, 0, length - 1);
    for (int i = 0; i < length - 1; i++)
        System.out.print(array[i] + " - ");

    }

}