`
huxiaoheihei
  • 浏览: 174246 次
  • 性别: Icon_minigender_2
  • 来自: 吉林
社区版块
存档分类
最新评论

八数码问题使用HashTable优化查找后的版本

 
阅读更多

 

在《双向广度优先搜索算法框架及八数码问题例程》一文中,给出了使用双向广度优先搜索算法解决八数码问题的一个

简单版本,查找都是线性的,没有优化。这里给出使用HashTable优化后的版本!

/*
 * Author: puresky
 * Date: 2010.01.12
 * Purpose: solve EIGTH NUMBER problem!
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXN 10000

#define SWAP(a, b) {char t = a; a = b; b = t;}

typedef struct _Node Node;

struct _Node
{
        char tile[10]; // represent the tile as a string ending with '\0'
        char pos;   // the position of 'x'
        char dir;  //the moving direction of 'x'
        int parent; //index of parent node
};

int head[2], tail[2];
Node queue[2][MAXN];// two queues for double directoin BFS

//shift of moving up, down, left ,right
int shift[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

//for output direction!
char dir[4][2] = {{'u', 'd'}, {'d', 'u'}, {'l', 'r'}, {'r', 'l'}};

//test case
char start[10] = "23415x768";
char end[10] = "12345678x";

/*=================hash table start=========================================*/

#define HASH_TABLE_MAX_SIZE 10000
typedef struct HashNode_Struct HashNode;

struct HashNode_Struct
{
        char* sKey;
        int nValue;
        HashNode* pNext;
};

HashNode* ht[2][HASH_TABLE_MAX_SIZE];//hash table data strcutrue

//initialize hash table
void hash_table_init(HashNode *hashTable[])
{
        memset(hashTable, 0, sizeof(HashNode*) * HASH_TABLE_MAX_SIZE);
}


//string hash function
unsigned int hash_table_hash_str(const char* skey)
{
        const signed char *p = (const signed char*)skey;
        unsigned int h = *p;
        if(h)
        {
                for(p += 1; *p != '\0'; ++p)
                        h = (h << 5) - h + *p;
        }
        return h;
}

//insert key-value into hash table
void hash_table_insert(HashNode *hashTable[], char* skey, int nvalue)
{

        unsigned int pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE;

        HashNode* pHead =  hashTable[pos];
        while(pHead)
        {
                if(strcmp(pHead->sKey, skey) == 0)
                {
                        printf("%s already exists!\n", skey);
                        return ;
                }
                pHead = pHead->pNext;
        }

        HashNode* pNewNode = (HashNode*)malloc(sizeof(HashNode));
        memset(pNewNode, 0, sizeof(HashNode));
        pNewNode->sKey = skey;
        pNewNode->nValue = nvalue;

        pNewNode->pNext = hashTable[pos];
        hashTable[pos] = pNewNode;

}

//lookup a key in the hash table
HashNode* hash_table_lookup(HashNode *hashTable[], const char* skey)
{
        unsigned int pos = hash_table_hash_str(skey) % HASH_TABLE_MAX_SIZE;
        if(hashTable[pos])
        {
                HashNode* pHead = hashTable[pos];
                while(pHead)
                {
                        if(strcmp(skey, pHead->sKey) == 0)
                                return pHead;
                        pHead = pHead->pNext;
                }
        }
        return NULL;
}

//free the memory of the hash table
void hash_table_release(HashNode *hashTable[])
{
        int i;
        for(i = 0; i < HASH_TABLE_MAX_SIZE; ++i)
        {
                if(hashTable[i])
                {
                        HashNode* pHead = hashTable[i];
                        while(pHead)
                        {
                                HashNode* pTemp = pHead;
                                pHead = pHead->pNext;
                                if(pTemp)
                                {
                                        free(pTemp);
                                }

                        }
                }
        }
}

/* ===============================hash table end=========================*/


//read a tile 3 by 3
void readtile()
{
        int i;
        char temp[10];
        for(i = 0; i < 9; ++i)
        {
                scanf("%s", temp);
                start[i] = temp[0];
        }
        start[9] = '\0';
}

//print result
void print_backward(int i)
{
        if(queue[0][i].parent != -1)
        {
                print_backward(queue[0][i].parent);
                printf("%c", queue[0][i].dir);
        }
}
void print_forward(int j)
{
        if(queue[1][j].parent != -1)
        {
                printf("%c", queue[1][j].dir);
                print_forward(queue[1][j].parent);
        }
}
void print_result(int i, int j)
{
        //printf("%d,%d\n", i, j);
        print_backward(i);
        print_forward(j);
        printf("\n");
}

//init the queue
void init(int qi, const char* state)
{
        strcpy(queue[qi][0].tile, state);
        queue[qi][0].pos = strchr(state, 'x') - state;
        queue[qi][0].parent = -1;

        head[qi] = tail[qi]  = 0;
}

//check if there are duplicates in the queue
//time comlexity:O(n)
//We can optimise this function using HashTable
int isduplicate(int qi)
{
        if(hash_table_lookup(ht[qi], queue[qi][tail[qi]].tile))
        {
                return 1;
        }
        return 0;
}

//check if the current node is in another queue!
//time comlexity:O(n)
//We can optimise this function using HashTable
int isintersect(int qi)
{
        HashNode* hn = hash_table_lookup(ht[1 - qi], queue[qi][tail[qi]].tile);
        if(hn)
        {
                return hn->nValue;
        }
        return -1;
}

//expand nodes
int expand(int qi)
{
        int i, x, y, r;

        Node* p = &(queue[qi][head[qi]]);
        head[qi]++;

        for(i = 0; i < 4; ++i)
        {
                x = p->pos / 3 + shift[i][0];
                y = p->pos % 3 + shift[i][1];
                if(x >= 0 && x <= 2 && y >= 0 && y <= 2)
                {
                        tail[qi]++;
                        Node* pNew = &(queue[qi][tail[qi]]);
                        strcpy(pNew->tile, p->tile);
                        SWAP(pNew->tile[ 3 * x + y], pNew->tile[p->pos]);
                        pNew->pos = 3 * x + y;
                        pNew->parent = head[qi] - 1;
                        pNew->dir = dir[i][qi];
                        if(isduplicate(qi))
                        {
                                tail[qi]--;
                        }
                        else
                        {
                                if((r = isintersect(qi)) != -1)
                                {
                                        if(qi == 1)
                                        {
                                                print_result(r, tail[qi]);
                                        }
                                        else
                                        {
                                                print_result(tail[qi], r);
                                        }
                                        return 1;
                                }
                                hash_table_insert(ht[qi], pNew->tile, tail[qi]);
                        }
                }
        }
        return 0;
}

//call expand to generate queues
int solve()
{
        init(0, start);
        init(1, end);
       
        while(head[0] <= tail[0] && head[1] <= tail[1])
        {
                //expand the shorter queue firstly
                if(tail[0] - head[0] >= tail[1] - head[1])
                {
                        if(expand(1)) return 1;
                }
                else
                {
                        if(expand(0)) return 1;
                }
        }
       
        while(head[0] <= tail[0]) if(expand(0)) return 1;
        while(head[1] <= tail[1]) if(expand(1)) return 1;
        return 0;
}

int main(int argc, char** argv)
{
        hash_table_init(ht[0]);
        hash_table_init(ht[1]);
        readtile();
        if(!solve())
        {
                printf("unsolvable\n");
        }
        hash_table_release(ht[0]);
        hash_table_release(ht[1]);
        //system("pause"); //pause
        return 0;
}

ACM PKU Judge Online: 940K 内存,32MS 时间

分享到:
评论

相关推荐

    Hashtable的使用

    **Hashtable的使用** 在Java编程语言中,`Hashtable`是一个基于键值对(key-value pairs)的数据结构,它属于同步的、线程安全的容器类。`Hashtable`是`Dictionary`类的一个子类,它不支持`null`键或`null`值。这个...

    HashTable

    《深入解析HashTable:...总结,C语言实现的HashTable涉及到哈希函数设计、冲突解决、插入查找删除操作以及性能优化等多个方面。理解这些核心概念和实现细节,有助于我们在实际开发中灵活应用哈希表,提高程序效率。

    WinFormHashTable最简单用法,.net hashtable ,hashtable ,hashtable用法

    - **性能优化**:虽然Hashtable提供快速访问,但如果哈希函数设计不当,可能导致冲突过多,降低性能。应合理选择键的类型和实现哈希函数,避免哈希冲突。 - **替代方案**:.NET Framework 2.0之后,推荐使用`...

    使用哈希表Hashtable填充ListBox

    本文将详细介绍如何使用`Hashtable`来填充`ListBox`,并探讨相关知识点。 1. 哈希表(HashTable)基础知识: - 哈希表基于哈希函数,通过计算键的哈希值来确定其在表中的位置,实现快速查找。 - `Hashtable`是...

    C# json 转hashtable

    然而,随着.NET Framework的发展,`Dictionary, TValue&gt;`逐渐取代了`Hashtable`,因为后者不支持泛型,且不遵循.NET Framework的线程安全策略。 标题"**C# json 转 hashtable**"涉及到的主要知识点是将JSON字符串...

    比hashtable查找起来方便,转换类型也简单

    总之,`Hashtable`虽然在早期的Java版本中被广泛使用,但由于其限制和性能原因,在现代Java开发中,我们通常会优先考虑使用`HashMap`、`ConcurrentHashMap`等替代品,以便更好地利用现代Java特性和提高代码效率。

    asp.net遍历hashtable

    在ASP.NET中,我们常常使用Hashtable来暂存和传递数据,比如在页面间传递状态信息。 遍历Hashtable主要有两种方法:foreach循环和GetEnumerator方法。 1. 使用foreach循环遍历: ASP.NET支持C#语言,C#的foreach...

    C#-Hashtable应用

    在本篇文档中,我们将深入探讨如何在C#中有效地使用Hashtable,并了解其基本操作和常见函数。 首先,让我们理解一下Hashtable的工作原理。Hashtable使用哈希表存储数据,通过计算键(key)的哈希码来定位元素的位置...

    C# .net HashTable

    此外,`Hashtable`在.NET Framework 4.0及以后版本中已被弃用,推荐使用`Dictionary, TValue&gt;`。 10. **比较与选择** - `HashTable` vs `Dictionary, TValue&gt;`:`Dictionary`在.NET Framework 2.0引入,它提供了...

    hashtable的使用

    ### 哈希表(Hashtable)的使用及自定义排序详解 #### 一、哈希表简介 哈希表(Hashtable)是一种数据结构,它通过一个哈希函数将键(Key)映射到表的一个位置来访问记录,这加快了查找记录的速度。哈希表在.NET ...

    hashtable存储数据.rar

    4. **不支持泛型**:由于`Hashtable`是早期Java版本的类,它没有使用泛型,因此键和值都使用`Object`类型,需要强制类型转换。 使用`Hashtable`的基本操作包括: - **插入元素**:使用`put(key, value)`方法将键值...

    HashTable 常用操作

    ### HashTable常用操作详解 #### 一、HashTable简介与.NET Framework中的实现 HashTable是一种非常重要的数据结构,在.NET ...通过学习这些知识点,开发者可以更好地理解和利用`Hashtable`来优化程序的性能。

    A*算法求解八数码问题_C#语言

    A*算法求解八数码问题 1、A*算法基本思想: 1)建立一个队列,计算初始结点的估价函数f,并将初始结点入队,设置队列头和尾指针。 2)取出队列头(队列头指针所指)的结点,如果该结点是目标结点,则输出路径,程序...

    HashMap和HashTable的区别和不同

    - **HashTable**: `HashTable`是一个线程安全的类,这意味着多个线程可以同时访问或修改`HashTable`而不会导致数据不一致的问题。`HashTable`通过同步每个方法的执行来实现这一点,即在执行`HashTable`的任何方法时...

    哈希表 Hashtable的操作使用

    ### 哈希表(Hashtable)的操作使用 #### 哈希表简介 哈希表是一种数据结构,它通过一个称为哈希函数的算法将键(Key)映射到值(Value)。在.NET Framework中,`Hashtable`类是实现哈希表的一个经典示例。它支持...

    c#通讯录hashtable

    在.NET Framework 2.0及以后的版本中,推荐使用泛型的`Dictionary, TValue&gt;`,它提供了更好的类型安全性和性能。 此外,`Hashtable`不支持排序,如果你需要按特定顺序遍历联系人,可能需要使用`SortedList`或`List...

    c#重写HashTable

    在C#编程中,`HashTable`是一个非泛型集合类,它在.NET Framework早期版本中被广泛使用。然而,随着.NET Framework的不断发展,`HashTable`逐渐被更安全、类型安全且性能更高的`Dictionary, TValue&gt;`所取代。尽管...

    hashMap和hashTable的区别

    如果需要线程安全,或者希望使用早期的 Java 版本中可用的集合类,可以选择 `HashTable`。然而,在现代 Java 开发实践中,推荐使用 `ConcurrentHashMap` 来代替 `HashTable`,因为它提供了更好的性能和更丰富的功能...

    HashTable的java实现

    在Java编程语言中,哈希表(HashTable)是一种常见的数据结构,它提供了高效的数据存储和检索功能。哈希表基于哈希函数将键(Key)映射到数组的索引位置,通过键值对(Key-Value Pair)来存储数据。这种数据结构允许...

    hashtable和hashmap的区别

    `Hashtable`的所有关键操作(如`put()`、`get()`)都是同步的,这意味着多个线程可以安全地访问同一个`Hashtable`实例而不会引发并发问题。 - **HashMap**: 不是线程安全的。默认情况下,`HashMap`的操作没有进行...

Global site tag (gtag.js) - Google Analytics