数据结构 哈希表、栈的应用与链式队列 6.29 (尾)
前言
来到这一篇博客,数据结构的这一阶段的学习也走向尾声。
这一篇有三个内容:哈希表(通过链地址法处理哈希冲突),括号匹配(运用栈的特性进行实现),以及链式队列的实现。
概述
1.哈希表
2.括号匹配
3.链式列队
1.哈希表
1.0 基本理论
由于直接定址法在存储数据时由于数据不连续,容易导致浪费空间的现象。因此采用除留余数法。散列函数为:H(key)=key/p,p一般取数据长度除0.75之后的最接近的质数。
但由于会出现多个数除留余数相等的情况,即哈希冲突。此时我们通过建立链表解决哈希冲突,如下图所示:
之后是代码实现:
1.1.makefile
EXE=01_hash
Objs=$(patsubst %.c,%.o,$(wildcard *.c))
CC=gcc
CFlags=-c -oall:$(EXE)
$(EXE):$(Objs)$(CC) $^ -o $@
%.o:%.c$(CC) $^ $(CFlags) $@#伪目标
.PHONY:clean
clean:rm $(EXE) $(Objs)
1.2.hash.h
#ifndef _HEAD_H_
#define _HEAD_H_#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 10
#define DEV 13typedef struct HashNode{union{int data;int len;};int result;struct HashNode* next;
}node,*node_p;typedef struct HashTable{node_p arr[DEV];
}table,*table_p;//fun
node_p create_head(int result);
node_p create_node(int value);
table_p create_Hash();
void sign_in_Hash(table_p T, int value);
void check(table_p T, int value);
void output(table_p T);#endif
1.3.fun.c
#include "hash.h"
//1
node_p create_head(int result){node_p H = (node_p)malloc(sizeof(node));H->len = 0;H->result = result;H->next = NULL;return H;
}
//2
node_p create_node(int value){node_p H = (node_p)malloc(sizeof(node));H->data = value;H->next = NULL;return H;
}
//3
table_p create_Hash(int len){if(len>MAX){printf("error\n");return NULL;}table_p H = (table_p)malloc(sizeof(table));for(int i = 0; i<=DEV-1; ++i){H->arr[i] = create_head(i);}return H;
}
//4
void sign_in_Hash(table_p T, int value){if(T == NULL){printf("error\n");return;}int result = value%13;for(int i = 0; i<=DEV-1; ++i){if(T->arr[i]->result == result){node_p new_p = create_node(value);node_p p = T->arr[i];p->len++;if(p->next!=NULL){new_p->next = p->next;}p->next = new_p;break;}}return;
}
//5
void check(table_p T, int value){if(T == NULL){printf("error\n");return;}int result = value%13;int flag = 0;node_p p = T->arr[result];while(p!=NULL){if(p->data == value){printf("exist\n");flag = 1;break;}p = p->next;}if(flag==0){printf("none\n");}return;
}
//6
void output(table_p T){if(T == NULL){printf("error\n");return;}for(int i = 0; i<=DEV-1; ++i){node_p p = T->arr[i]->next;while(p!=NULL){printf("%d ",p->data);p = p->next;}}printf("\n");return;
}
1.4.main.c
#include "hash.h"
int main(int argc, const char *argv[])
{int arr_start[10] = {25,51,8,22,26,67,11,16,54,41};table_p H = create_Hash(10);for(int i = 0; i<=9; ++i){sign_in_Hash(H,arr_start[i]);}check(H,22);output(H);free(p);p = NULL;return 0;
}
1.5.run
ubuntu@ubuntu:~/data_structre/vacation/hash$ ./01_hash
exist
26 41 54 67 16 8 22 11 51 25
ubuntu@ubuntu:~/data_structre/vacation/hash$
对照上分图片,数据已经按哈希表的顺序排列好,数据的存入与查找也运作正常。
2.括号匹配(栈)
2.1.makefile
EXE=01_bracket
Objs=$(patsubst %.c,%.o,$(wildcard *.c))
CC=gcc
CFlags=-c -oall:$(EXE)
$(EXE):$(Objs)$(CC) $^ -o $@
%.o:%.c$(CC) $^ $(CFlags) $@#伪目标
.PHONY:clean
clean:rm $(EXE) $(Objs)
2.2.bracket.h
#ifndef _HEAD_H_
#define _HEAD_H_#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 128typedef struct stack{char arr[MAX];int top;
}stack,*stack_p;//fun
stack_p create_stack();
void input(char* str);
void match(char a,char b);
void filter(stack_p S, char*str);#endif
2.3.fun.c
#include "bracket.h"
//create stack
stack_p create_stack(){stack_p S = (stack_p)malloc(sizeof(stack));memset(S,0,sizeof(stack));S->top=-1;return S;
}//1
void input(char* str){printf("请输入需要匹配括号的字符串:\n");scanf("%s",str);str[strcspn(str,"\n")]='\0';
}
//2
void match(char a,char b){if((a=='('&&b==')')\||(a=='['&&b==']')\||(a=='{'&&b=='}')){printf("matching successed\n");}else{printf("matching failed\n");}
}
//3
void filter(stack_p S, char*str){if(S==NULL){printf("error");return;}int len = strlen(str);for(int i = 0; i<=len-1; ++i){if(str[i]=='('\||str[i]=='['\||str[i]=='{'){S->top++;S->arr[S->top]=str[i];}if(str[i]==')'\||str[i]==']'\||str[i]=='}'){match(S->arr[S->top],str[i]);S->top--;}}//puts(S->arr);return;
}
2.4.main.c
#include "bracket.h"
int main(int argc, const char *argv[])
{char str[128]={0};input(str);stack_p S = create_stack();filter(S,str);return 0;
}
2.5.run
ubuntu@ubuntu:~/data_structre/vacation/bracket$ ./01_bracket
请输入需要匹配括号的字符串:
(dksdhjs)[]
matching successed
matching successed
ubuntu@ubuntu:~/data_structre/vacation/bracket$ ./01_bracket
请输入需要匹配括号的字符串:
(dhshdj[)]
matching failed
matching failed
注意,上图中的第二种情况括号错开实际上属于匹配失败,因此试图通过对左右括号计数来判断匹配性是有问题的(不要问我怎么知道的......)
3.链式列队
3.1.makefile
EXE=01_lque
Objs=$(patsubst %.c,%.o,$(wildcard *.c))
CC=gcc
CFlags=-c -oall:$(EXE)
$(EXE):$(Objs)$(CC) $^ -o $@
%.o:%.c$(CC) $^ $(CFlags) $@#伪目标
.PHONY:clean
clean:rm $(EXE) $(Objs)
3.2.lque.h
#ifndef _HEAD_H_
#define _HEAD_H_#include <stdio.h>
#include <string.h>
#include <stdlib.h>typedef struct queue{int data;struct queue* next;
}queue,*queue_p;typedef struct head{queue_p front;queue_p rear;
}head,*head_p;head_p create_head();
queue_p create_node(int value);
void input(head_p H,int value);
int output(head_p H);
void show(head_p H);
#endif
3.3.fun.c
#include "lque.h"
//1
head_p create_head(){head_p H = (head_p)malloc(sizeof(head));H->front = NULL;H->rear = NULL;return H;
}
//2
queue_p create_node(int value){queue_p Q = (queue_p)malloc(sizeof(queue));Q->data = value;Q->next = NULL;return Q;
}
//3
//列队的特性:尾进
void input(head_p H,int value){queue_p new = create_node(value);new->next = NULL;new->data = value;if(H->rear!=NULL){H->rear->next = new;}H->rear = new;if(H->front == NULL){H->front = new;}return;
}
//4
//头出
int output(head_p H){if(H->front == NULL)return -999;queue_p p_del = H->front;H->front = H->front->next;int out_data = p_del->data;free(p_del);return out_data;
}
//5
void show(head_p H){if(H->front == NULL)return;queue_p p = H->front;while(p!=NULL){printf("%d ",p->data);p=p->next;}printf("\n");return;
}
3.4.main.c
#include "lque.h"
int main(int argc, const char *argv[])
{head_p H = create_head();input(H,1);input(H,2);input(H,3);input(H,4);input(H,5);show(H);int num = output(H);printf("output:%d\n",num);printf("after:");show(H);return 0;
}
3.5.run
ubuntu@ubuntu:~/data_structre/vacation/linked queue$ make
gcc main.c -c -o main.o
gcc fun.c -c -o fun.o
gcc main.o fun.o -o 01_lque
ubuntu@ubuntu:~/data_structre/vacation/linked queue$ ./01_lque
1 2 3 4 5
output:1
after:2 3 4 5
ubuntu@ubuntu:~/data_structre/vacation/linked queue$ .
尾进头出。
结语
以上。