刚学C语言指针时,只对其初始化一掠而过,导致在数据结构的编程中老是出现编译错误,既浪费时间又无益于于效率。为此,今天特地总结一下指针的初始化。
下面以开放定址法处理处理冲突的哈希表的测试文件作说明:
#include <stdio.h>
#include <stdlib.h>
#include "kfdz-hash.h"
int Hash(int key,int size){ //hash的构造函数
return key%size;
}
void collision(int *hashValue, int hashSize){ //查看下一个地址
*hashValue= (*hashValue+1)%hashSize;
}
int main()
{
int i,a = 0,b = 0;
int *d ;
int *e ;
d = &a; //若省去这一行会出现编译错误,因为此时的指针是“野指针”,不受“控制”
e = &b; //若省去这一行会出现编译错误,因为此时的指针是“野指针”,不受“控制”
int n = -1000;
int Hash(int,int);
void collision();
int hashsize = 4;
int key[] = {11,1,2,3,4,5,6};
Node *np1 = (Node *)malloc(sizeof(Node));
HashTable *H = (HashTable *)malloc(sizeof(HashTable)); //需为其开辟空间,否则下面的调用会出错,类似于“野指针”
InitHash(H ,hashsize, Hash,collision);
printf("插入后全部输出以及冲突次数\n");
for(i = 0; i < 6; i ++){ //插入元素并判断是否重构
if(H->count >= H->size)H = expandHash(H,2 * H->size);
InsertHash( H , key[i] );}
for(i = 0; i < 6; i ++){
*e = 0; //搜索元素并输出
printf("%d ",SearchHash( H, key[i] , d, e)->key);
printf("%d\n",*e);}
printf("\n\n删除个别元素后全部输出\n");
deleteHash(H, 5); //删除元素
deleteHash(H, 1);
for(i = 0; i < 6; i ++){
np1 = SearchHash(H, key[i],d,e);
printf("%d ",np1 == NULL?n:np1->key);
}
printf("\n");
DestroyHash(H);
return 0;
}
需理解调用函数中的指针变量值改变并不影响原指针变量值,只有指针变量所指向的变量值改变才会影响原指针所指向的变量值。这里需注意指针变量的值以及指针变量所指向的变量值。
下面以哈希表的实现文件来说明:
#include <stdio.h>
#include <stdlib.h>
#include "kfdz-hash.h"
//初始化Status InitHash(HashTable *H, int size, int (*hash)(int, int), void (*collision)(int *,int)){ int i; H->rcd = (Node *)malloc(size*sizeof(Node)); //H->tag = (int *)malloc(size*sizeof(int)); if(H->rcd == NULL)return ERROR; for(i = 0; i < size; i ++)H->rcd[i].tag = 0; H->size = size; H->hash = hash; H->collision = collision; H->count = 0; return OK; }Status DestroyHash(HashTable *H){ free(H); return OK; //else return ERROR;}Node *SearchHash(HashTable *H,int key,int *p , int *c){ *p = H->hash(key, H->size); int a = 0; int *q = &a; *q = *p; while(1 == H->rcd[*p].tag && H->rcd[*p].key != key || -1 == H->rcd[*p].tag){ H->collision(p,H->size);(*c) = *c + 1; if(*q == *p)break;//如果找一遍后回到原处就退出 } if(H->rcd[*p].key == key && 1 == H->rcd[*p].tag){ return &H->rcd[*p];} else return NULL; }Status InsertHash(HashTable *H,int key){ int a = 0,b = 0; int *c ; int *j ; c = &a; j = &b; if(NULL == SearchHash(H, key, j, c)){ int k = *j; /*if( H->count >= H->size){ printf("%d " , key); H = expandHash( H, 2 * (H->size)); SearchHash(H,key,j,c); H->rcd[*j].key = key; H->rcd[*j].tag = 1; H->count++; return OK; }*/ /*省略代码为哈希表重构的执行, 若此执行在search中进行,无法完成重构, 因为重构得到的指针只是赋给search中的指针变量参数H, 让其不指向传递过来的指针,无法改变原指针的指向,故重构失败。*/ H->rcd[k].key = key; H->rcd[k].tag = 1; H->count++; return OK; } return ERROR;}Status deleteHash(HashTable *H,int key){ int a = 0,b = 0; int *c = &a; int *j = &b; if(SearchHash(H, key, j, c) != NULL){ H->rcd[(*j)].tag = -1; return OK; } else return ERROR; }HashTable * expandHash(HashTable *H,int expand){ int i; HashTable *h = (HashTable *)malloc((H->size+expand)*sizeof(HashTable)); if( h == NULL) return ERROR; InitHash(h , H->size+expand, H->hash,H->collision); for(i = 0; i < H->size; i++){ if(H->rcd[i].tag == 1)InsertHash(h,H->rcd[i].key); } free(H); return h;}
以下为哈希表的头文件:
#ifndef _KFDZ-HASH_H
#define _KFDZ-HASH_H
#define OK 1
#define ERROR 0
typedef int Status;
typedef struct node{
int key;
int tag;
}Node;
typedef struct {
Node* rcd;
int size;
int count;
int (*hash)(int key, int hashSize); //函数指针
void (*collision)(int *hashValue,int hashSize);
}HashTable;
Status DestroyHash(HashTable *H);
Node *SearchHash(HashTable *H,int key,int *p , int *c);
Status InsertHash(HashTable *H,int key);
Status deleteHash(HashTable *H,int key);
HashTable *expandHash(HashTable *H,int expand);
Status InitHash(HashTable *H, int size, int (*hash)(int, int),
void (*collision)(int *,int));
#endif