刚学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