您的位置:首页 > 运维架构 > Linux

linux中list结构应用及构造hashtable进行英文文章单词数统计

2016-01-02 13:49 661 查看














一。传统的list和linux中内核list结构对比,内核中的list更灵活

























六程序如下

hashtable.h

#include "list.h"
#include<string.h>
#include<malloc.h>

#define HASHTABEL_LEN 26
//以每个单词前面两个字母叠加作为hashtable的key值

struct hash_node
{
struct list_head openlist;//开链法用来索引的链表
int sum;
char* word;
};

struct hash_table
{
hash_node hashtable[HASHTABEL_LEN];
};

void init_hash_table(hash_table &hashtable)
{
int i;
for (i=0;i<HASHTABEL_LEN;i++)
{
INIT_LIST_HEAD(&(hashtable.hashtable)[i].openlist);
}
}

//将单词添加到hashtable中
void insert_list_node(hash_node *hashtable, hash_node *newnode)
{
hash_node *tmp;
char *tmpword=newnode->word;
hash_node* bucket=&hashtable[(*tmpword-'a')];
struct list_head*  pos;
list_for_each(pos,&(bucket->openlist))
{
tmp=list_entry(pos,hash_node,openlist);
if(strcmp(tmp->word,newnode->word)==0)
{
++(tmp->sum);
free(newnode->word);
free(newnode);
break;
}
else
{
list_add_tail(&(newnode->openlist),&(tmp->openlist));
break;
}
}
if(pos==&(bucket->openlist))
{
list_add_tail(&(newnode->openlist),&(bucket->openlist));

}

}


list.h

#ifndef _LIST_H_
#define _LIST_H_

/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/

struct list_head {
struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)

#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

/*
* Insert a _new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *_new, struct list_head *prev, struct list_head *next)
{
next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}

/**
* list_add - add a _new entry
* @_new: _new entry to be added
* @head: list head to add it after
*
* Insert a _new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *_new, struct list_head *head)
{
__list_add(_new, head, head->next);
}

/**
* list_add_tail - add a _new entry
* @_new: _new entry to be added
* @head: list head to add it before
*
* Insert a _new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *_new, struct list_head *head)
{
__list_add(_new, head->prev, head);
}

/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}

/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}

/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}

/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(struct list_head *head)
{
return head->next == head;
}

/**
* list_splice - join two lists
* @list: the _new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
struct list_head *first = list->next;

if (first != list) {
struct list_head *last = list->prev;
struct list_head *at = head->next;

first->prev = head;
head->next = first;

last->next = at;
at->prev = last;
}
}

/**
* list_entry - get the struct for this entry
* @ptr:        the &struct list_head pointer.
* @type:       the type of the struct this is embedded in.
* @member:     the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

/**
* list_for_each        -       iterate over a list
* @pos:        the &struct list_head to use as a loop counter.
* @head:       the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)

/**
* list_for_each_safe   -       iterate over a list safe against removal of list entry
* @pos:        the &struct list_head to use as a loop counter.
* @n:          another &struct list_head to use as temporary storage
* @head:       the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)

/**
* list_for_each_entry  -       iterate over list of given type
* @pos:        the type * to use as a loop counter.
* @head:       the head for your list.
* @member:     the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member, type) \
for (pos = list_entry((head)->next, type, member);\
&pos->member != (head);\
pos = list_entry(pos->member.next,type, member))

/**
* list_for_each_entry_safe  - 遍历时删除节点list_for_each_entry的一种安全用法
* @pos:        the type * to use as a loop counter.
* @n:          another &struct list_head to use as temporary storage
* @head:       the head for your list.
* @member:     the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member, type) \
for (pos = list_entry((head)->next, type, member), n = pos->member.next;\
&pos->member != (head);\
pos = list_entry(n, type, member), n = pos->member.next)

#endif
hashtabletest.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include "hashtable.h"

#include"list.h"

#include<iostream>
using namespace std;

#define FILE_NAME_MAX_LEN 256 /* the max length of the file */
//#define HASHTABEL_LEN     26  /* the length of hash table, cause there are 26 low case letters*/
#define SUCCESS           0   /* file operation flag */
#define FAILURE           1

/*getword
function: get the words in the file
*/
int getword(FILE *fp, char **word_temp)
{
int ch;
unsigned long num;
num=0;
while(!feof(fp))
{
ch=fgetc(fp);
if(isalpha(ch))
{
num++;
break;
}
}

while (!feof(fp))
{
ch = fgetc(fp);
if (isalpha(ch)) {
num++;
} else
{
break;
}
}

if (!feof(fp))
{
(void)fseek(fp,-(num+1),1);
*word_temp = (char *)malloc(num+1);
if (word_temp == NULL)
{

(void)fprintf(stdout,"Sorry, the memory space is full");
(void)fprintf(stdout,"Please input any key to exit the program\n");
(void)getchar();
exit(FAILURE);
}
(void)fgets(*word_temp,num+1,fp);
(void)fseek(fp,1,1);
return SUCCESS;
}
else
{
if (num != 0) {
*word_temp = (char *)malloc(num+1);
if (word_temp == NULL)
{

(void)fprintf(stdout,"Sorry,the memory space is full");
(void)fprintf(stdout,"Please input any key to exit program....\n");
(void)getchar();
exit(FAILURE);
}
(void)fseek(fp,-(num),SEEK_CUR);
(void)fgets(*word_temp,num+1,fp);
return SUCCESS;
}
}
return FAILURE;
}

//保存
void save_hashtable_node(hash_table &hashtable)
{
hash_node *head, *tmp;
struct list_head *pos, *q;
int i;
FILE *fp;

char filename[50];
cout<<"请输入要输出的文件名"<<endl;
cin.getline(filename,50);

if((fp=fopen(filename,"w"))==NULL)
{
(void)fprintf(stdout,"Sorry, failure to open the file\n");
(void)fprintf(stdout,"Please input any key to exit the program\n ");
(void)getchar();
(void)exit(FAILURE);
}

for (i=0;i<HASHTABEL_LEN;i++)
{
head=hashtable.hashtable+i;
list_for_each_safe(pos,q, &(head->openlist))
{
tmp=list_entry(pos, hash_node,openlist);
(void)fprintf(fp,"%s,%d\r\n",tmp->word,tmp->sum);
(void)list_del(pos);
(void)free(tmp->word);
(void)free(tmp);
}
}
(void)fprintf(stdout,"file successfully saved \n");
fclose(fp);
}

//显示
void display_hashtable_node(hash_node *hashtable)
{
hash_node *head, *tmp;
struct list_head *pos, *q;
int i;
(void) fprintf(stdout, "结果如下:\n");
for(i=0; i<HASHTABEL_LEN; i++)
{
head=hashtable+i;
list_for_each_safe(pos, q,&(head->openlist))
{
tmp=list_entry(pos, hash_node,openlist);
(void)fprintf(stdout,"%s,%d\n",tmp->word,tmp->sum);
}
}
}

int main()
{
FILE *fp;
hash_table hashtable;
hash_node *_new;
char *word_tmp;
char filename[50];
cout<<"请输入要统计的文件名"<<endl;
cin.getline(filename,50);
fp=fopen(filename,"rb");

init_hash_table(hashtable);
while(!feof(fp))
{
if(getword(fp,&word_tmp)==SUCCESS)
{
_new=(hash_node *)malloc(sizeof(hash_node));
if(_new==NULL)
{
(void)fprintf(stdout,"Sorry,the memory space is full");
(void)exit(FAILURE);
}
_new->sum=1;

//将单词转换成小写
int i=0;
while (*(word_tmp+i)!='\0')
{
*(word_tmp+i)=tolower(*(word_tmp+i));
i++;
}

_new->word=word_tmp;
insert_list_node(hashtable.hashtable,_new);

}

}

fclose(fp);
display_hashtable_node(hashtable.hashtable);
save_hashtable_node(hashtable);
fprintf(stdout,"please input any key to exit the program\n");
getchar();
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: