Estrutura de dados da Universidade de Zhejiang MOOC-11-Hash 1 Louco por bate-papo por telefone (25 pontos)

Registro de erro:
1. Os dois códigos a seguir são equivalentes, embora eu não entenda muito bem

char Data[KEYLENGTH+1];
//与
typedef char ElementType[KEYLENGTH + 1];//不十分理解
ElementType Data;

2. Conversão de tipo
para (i = (int) sqrt (q); i> 2; –i) {// sqr usado incorretamente Outro: Por que usar protótipo de função q de dupla precisão: double sqrt (double x);
aqui está OK Fale sobre os pequenos pontos de conhecimento da conversão de tipo. Quando a função é chamada, a declaração forçará a conversão de tipo dos parâmetros. Portanto, também é possível usar o inteiro p como um argumento aqui, mas executei duas vezes e encontrei que é usado diretamente O tempo de execução do programa em p é o dobro do tempo de uso da variável q. (Não sei por quê)
Insira a descrição da imagem aqui
3. if (p% i == 0) break; //% só pode ser usado para operações inteiras,% é o operador de resto, que só pode ser usado para operações inteiras e inteiras, se usado Para operações não inteiras, o programa relatará um erro e fará com que ele falhe ao ser executado.
4. H-> Heads = (PtrToLNode) malloc (H-> TableSize * sizeof (struct LNode));
// Este é um array dinâmico, H-> Heads é o primeiro endereço do array dinâmico, e os elementos no array são struct LNode, pensei erroneamente que os elementos do array dinâmico aplicado eram variáveis ​​de ponteiro.
5. H-> TableSize = NextPrime (TableSize); // uso incorreto TableSize = NextPrime (TableSize)
O objetivo aqui é atribuir um valor ao membro TableSize da tabela hash H, mas esqueci de escrever H.
6. p [i] é igual a * (p + i), ambos são os objetos apontados pelo ponteiro p, e (p + i) é um ponteiro, para usar o operador ->
7.

(H->Heads+i)->Data[0] = '\0';//wrong used H->Heads[i]->Data = '\0'; 
      	//这里的Data是一个数组,还有事我没懂
      	//想不明白 这个H->Heads难道不是指针么,对他是一个指针,但是对指针加[]就相当于解引用,此时H->Heads[i]为指针指向的节点
      	H->Heads[i].Next = NULL;
      	H->Heads[i].cnt = 0;

8.while (* Key! = '\ 0') {// errado usado if (* Key! = '\ 0')
Escrevi incorretamente enquanto como se, passei nos primeiros dois testes, e o terceiro atingiu o tempo limite. A chave aqui está um ponteiro, a ordem de operação de * Key ++, a prioridade do operador de endereçamento indireto e o operador de incremento 1 são dois, mas a direção da combinação é a combinação certa, então é na verdade equivalente a * (Key ++), então está certo O ponteiro é incrementado em um.
9. P = H-> Cabeças [h]. Próximo;
// usado incorretamente P = H-> Cabeças + h Este é o desempenho de não compreender a estrutura de dados da tabela hash, o nó principal na tabela hash não armazenamento de dados

Index Hash(const char *Key,int TableSize){
    
    
  	unsigned int h=0;
    while(*Key!='\0'){
    
    //wrong used if(*Key!='\0')
      	h += (h << 5) + *Key++;//wrong used h += (Key<<5) + Key++;
    }
  	return h%TableSize;
}
#include<math.h>
#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXTABLESIZE 1000000 //为啥
#define HASHNUM 5
#define KEYLENGTH 11

typedef char ElementType[KEYLENGTH + 1];//不十分理解
typedef int Index;

typedef struct LNode *PtrToLNode;
struct LNode{
    
    
    PtrToLNode Next;
    int cnt;
    ElementType Data;
};
typedef PtrToLNode Position;

//散列表节点定义
typedef struct TableNode *HashTable;//不十分理解为什么这么命名
struct TableNode{
    
    
    int TableSize;
    PtrToLNode Heads;//这是一个数组,每个节点都是LNode
};

int NextPrime(int N){
    
    
		int i,p = (N%2)? (N+2):(N+1);
  	double q = p;
  	while(q<MAXTABLESIZE){
    
    
      	for(i=(int)sqrt(q);i>2;--i){
    
    //wrong used sqr 另:为什么要使用双精度的q     double sqrt(double x);
          	if(p%i==0) break; //%只能用于整数运算的运算符,%是求余运算符,只能适用于整数与整数运算,如果用于非整数运算,程序会报错导致无法运行。
				}
      	if(i==2) break;
      	else p += 2;
    }
  	return p;
}
HashTable CreateTable(int TableSize){
    
    
  	HashTable H;
  	int i;
  	H = (HashTable)malloc(sizeof(struct TableNode));
  	H->TableSize = NextPrime(TableSize);//wrong used TableSize = NextPrime(TableSize)
  	H->Heads = (PtrToLNode)malloc(H->TableSize*sizeof(struct LNode));
  	//这是一个动态数组,H->Heads为动态数组首地址,数组中的元素为struct LNode
  	for(i=0;i<H->TableSize;++i){
    
    
      	(H->Heads+i)->Data[0] = '\0';//wrong used H->Heads[i]->Data = '\0'; 
      	//这里的Data是一个数组,还有事我没懂
      	//想不明白 这个H->Heads难道不是指针么,对他是一个指针,但是对指针加[]就相当于解引用,此时H->Heads[i]为指针指向的节点
      	H->Heads[i].Next = NULL;
      	H->Heads[i].cnt = 0;
    }
  	return H;  
}
Index Hash(const char *Key,int TableSize){
    
    
  	unsigned int h=0;
    while(*Key!='\0'){
    
    //wrong used if(*Key!='\0')
      	h += (h << 5) + *Key++;//wrong used h += (Key<<5) + Key++;
    }
  	return h%TableSize;
}
Position Find(HashTable H,ElementType Key){
    
    
  	Position P;
  	Index h;
  	h = Hash(Key+KEYLENGTH-HASHNUM,H->TableSize);//wrong used h = Hash(Key-KEYLENGTH+HASHNUM,H->TableSize)
  	P = H->Heads[h].Next;
  	//wrong used P = H->Heads+h这就是没懂散列表数据结构的表现,散列表中的列表头节点不存储数据
  	while(P && strcmp(Key,P->Data)){
    
    
      	P = P->Next;
    }  	
  	return P;
}
bool Insert(HashTable H,ElementType Key){
    
    
  	Position P,NewCell;
  	Index pos;
  	P = Find(H,Key);
  	if(!P){
    
    
      	NewCell = (PtrToLNode)malloc(sizeof(struct LNode));
      	strcpy(NewCell->Data,Key);//wrong used strcopy(NewCell->Data,Key);
      	NewCell->cnt = 1;//现在有点懵 这个cnt保存的是什么 哦想起啦了 狂人打电话次数
      	pos = Hash(Key+KEYLENGTH-HASHNUM,H->TableSize);
      	NewCell->Next = H->Heads[pos].Next;
      	H->Heads[pos].Next = NewCell;
      	return true;
    }
  	else{
    
    
      	P->cnt++;
      	return false;
    }
}
void DestroyTable(HashTable H){
    
    
  	int i;
  	PtrToLNode P,temp;
  	for(i=0;i<H->TableSize;++i){
    
    
      	P = H->Heads[i].Next;
      	while(P){
    
    
          	temp = P->Next;
          	free(P);
          	P = temp;
        }
    }
  	free(H->Heads);
  	free(H);
}
void ScanAndOutput(HashTable H){
    
    
  	int i,Mcnt=0,Pcnt=0;
  	ElementType MinPhone;
  	MinPhone[0] = '\0';//其实我不太懂为什么这样初始化
  	PtrToLNode P;
  	for(i=0;i<H->TableSize;++i){
    
    
      	P = H->Heads[i].Next;
      	while(P){
    
    
          	if(P->cnt>Mcnt){
    
    
              	Mcnt = P->cnt;
              	strcpy(MinPhone,P->Data);
              	Pcnt = 1;
            }
          	else if(P->cnt==Mcnt){
    
    
              	if(strcmp(MinPhone,P->Data)>0){
    
    
                  	strcpy(MinPhone,P->Data);
                }
              	Pcnt++;
            }
          	P = P->Next;//我竟然忘了这个
        }
    }
  	printf("%s %d",MinPhone,Mcnt);
  	if(Pcnt>1) printf(" %d",Pcnt);
  	printf("\n");
}
int main(){
    
    
  	HashTable H;
  	int i,N;
  	ElementType Key;
  	scanf("%d",&N);
  	H = CreateTable(2*N);
  	for(i=0;i<N;++i){
    
    
      	scanf("%s",Key);Insert(H,Key);
      	scanf("%s",Key);Insert(H,Key);
    }
  	ScanAndOutput(H);
	DestroyTable(H);
  	return 0;
}

Acho que você gosta

Origin blog.csdn.net/weixin_43919570/article/details/105897583
Recomendado
Clasificación