倒排索引(Reverted Index)-java实现

这是信息检索课老师布置的题目,
1、题目:重现下图1(来自书籍:Introduction to Information Retrieval):
这里写图片描述

图1

2、直接上源码和结果,代码注释写得很清楚了:

public class InvertedIndexs {

    private static String[] docs = {
            "I did enact Julius Caesar: I was killed i’ the Capitol; Brutus killed me",
            "So let it be with Caesar. The noble Brutus hath told you Caesar was ambitious",
            "I did enact Julius Caesar: I was killed i’ the Capitol; Brutus killed me",
            "So let it be with Caesar. The noble Brutus hath told you Caesar was ambitious",
            "One Sunday morning the local post office delivered an important special delivery letter to my home",
            "More than a year later I needed a post-office box for a new business I was starting",
            "I wrote the postmaster a note of appreciation. "
            };
    private static int n = docs.length;// 文档数
    private static Map<String, Set<Integer>> reverted_indexs;

    public static void main(String[] args) {
        revertedIndex();//建立倒排索引
        String str1="I",str2="a";
        List<Integer> results=intersect(str1,str2);
        display();//显示和排序
        show(str1,str2,results);
    }
    private static void show(String str1, String str2, List<Integer> results) {


        System.out.println("同时出现 "+str1+" 和 "+str2 +" 的文章有:");
        if(results==null){
            System.out.println("无");
            return;
        }
        System.out.println(results);
    }
    /**
     * 查找同时出现term1和term2的所有文章
     * @param term1 
     * @param term2 
     * @return 返回文章id数组
     */
    private static List<Integer> intersect(String term1, String term2) {
        Set<Integer> texts1=reverted_indexs.get(term1);
        Set<Integer> texts2=reverted_indexs.get(term2);
        if(texts1==null||texts2==null)//如果term1或term2从未出现过,返回null
            return null;
        Object[] texts_1=texts1.toArray();
        Object[] texts_2=texts2.toArray();
        List<Integer> results=new ArrayList<Integer>();
        int i=0,j=0;
        //查找同时出现term1和term2的所有文章,算法复杂度是线性的
        for(;i<texts_1.length&&j<texts_2.length;){
            if(texts_1[i]==texts_2[j]){
                results.add((Integer) texts_1[i]);
                i++;j++;
            }else if((Integer)texts_1[i]<(Integer)texts_2[j])
                i++;
            else
                j++;

        }
        return results;
    }
    /**
     * 根据key来排序,忽略大小写,
     * 显示每个term出现在什么文章中
     */
    private static void display() {
        Object[] key = reverted_indexs.keySet().toArray();
        List<Object> list=Arrays.asList(key);
        System.out.println("词项   文档频率 倒排记录表");
        //根据key来排序,忽略大小写
        Collections.sort(list,new Comparator<Object>() {
            @Override
            public int compare(Object o1, Object o2) {
            //此处排序有一个bug,最后两个元素没有排序
                return ((String) o1).compareToIgnoreCase ((String) o2);
            }
        });
        Set<Integer> temp;
        for (int i = 0; i < key.length; i++) {//显示每个term出现在什么文章中
            temp=reverted_indexs.get(key[i]);
            System.out.println((String) key[i]+" "+ temp.size() +"-->"+ temp);
        }
    }
    /**
     * 建立倒排索引
     */
    private static void revertedIndex() {
        reverted_indexs = new HashMap<String, Set<Integer>>();
        String[] upd_docs = new String[n];
        String[] terms;
        int i = 0,  j;
        for (i = 0; i < n; i++) {
            upd_docs[i] = docs[i].replaceAll(";|:|\\.", "");//将文档中标点:;.去除
            terms = upd_docs[i].split(" ");
            for (j = 0; j < terms.length; j++) {
                if (!reverted_indexs.containsKey(terms[j])) {//新建一个term的索引
                    Set<Integer> sub = new HashSet<Integer>();
                    sub.add(i + 1);
                    reverted_indexs.put(terms[j], sub);
                } else {                                    //在一个已存在的索引中加入文章编号
                    Set<Integer> sub = reverted_indexs.get(terms[j]);
                    sub.add(i + 1);
                }
            }
        }
    }
}

3、结果:
这里写图片描述

图2

这里写图片描述
图3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值