⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p372.cpp

📁 第一次上传
💻 CPP
字号:
		int IsPrime ( int N ) {					//测试N是否质数
		   for ( int i=3; i*i<=N; i+=2 )				//若N能分解为两个整数的乘积, 其中一个一定 
			 if ( N % i == 0 ) return 0;			//N能整除i, N不是质数
		   return 1;							//N是质数
		}

		int NextPrime ( int N ) {					//求下一个>N的质数,设N >= 5
		   if ( N % 2 == 0 ) N++;				//偶数不是质数
		   for ( ; !IsPrime (N); N+=2 );				//寻找质数
		   return N;
		}

		template <class Type> class HashTable {				//散列表类的定义
		public:
		   enum KindOfEntry { Active, Empty, Deleted };			//表项分类 (活动 / 空 / 删)
		   int Find ( const Type & x );				//在散列表中搜索x
		   int IsEmpty ( ) { return !CurrentSize ? 1 : 0; }			//判散列表空否,空则返回1 
		   int IsFull ( ) { return CurrentSize == TableSize ? 1 : 0; }	//判散列表满否,满则返回1
		   int Insert ( const Type & x );
		   int Remove ( const Type & x );
		   int IsIn ( const Type & x );
		   int WasFound ( ) const { return LastFindOK;	}		//判最近一次搜索是否成功
		   //其它共有函数与定义10.6声明线性探查散列表类相同
		   HashTable ( int sz=DefaultSize ) : TableSize ( sz ) { AllocateHt ( );  CurrentSize = 0; }		//构造函数
		   ~HashTable ( ) { delete [ ] ht; }						//析构函数
		   const HashTable & operator = ( const HashTable & ht2 );		//重载函数:表赋值
		   int FindPos ( const Type & x ); 					//散列函数: 计算含x表项的初始桶号
		   void MakeEmpty ( );								//置散列表为空

		private:
		   struct HashEntry {							//散列表的表项定义
		      Type Element;							//表项的数据, 即表项的关键码
		      KindOfEntry info;							//三种状态: Active, Empty, Deleted
		      HashEntry ( ) : info (Empty ) { }					//表项构造函数
		      HashEntry ( const Type &E, KindOfEntry i = Empty ) : Element (E), info (i) { };
		   };
		   //enum { DefualtSize = 11; };
		   HashEntry *ht; 								//散列表存储数组
		   int TableSize;								//数组长度,要求是满足4k+3的质数,k是整数
		   int CurrentSize;								//已占据散列地址数目
		   int LastFindOK;							//若最近一次搜索成功成功, 则返回1
		   void AllocateHt ( ) { ht = new HashEntry[TableSize ]; }	//分配散列表存储空间的函数
		};
		template <class Type> int HashTable<Type>::Find ( const Type & x ) {
		//共有函数: 找下一散列位置的函数
		   int i = 0,  odd = 0 ;								// i为探查次数,odd是控制加减标志
		   int CurrentPos = FindPos ( x );						//利用散列函数计算x的散列地址
		   while ( ht[CurrentPos].info != Empty && ht[CurrentPos].Element != x ) {	//搜索是否要求表项
			 if ( !odd ) {									// odd == 0为(H0 + i2)%TableSize情形
			   CurrentPos += 2*++i - 1;   odd = 1;				//求“下一个”桶
		 	   while ( CurrentPos >= TableSize ) CurrentPos -= TableSize;	//实现取模
			 }
			 else {										// odd == 1为(H0 - i2)%TableSize情形
			   CurrentPos -= 2*i-1;  odd = 0;					//求“下一个”桶
			   while ( CurrentPos < 0 ) CurrentPos += TableSize; 		//实现取模
			 }
		   }
		   LastFindOK = ht[CurrentPos].info == Active;				//记下最后是否搜索成功信息
		   return CurrentPos;								//返回桶号
		};

		template <class Type> int HashTable<Type>::Insert ( const Type & x ) {
		//将x插入到散列表中, 若x在表中已存在, 则返回0, 否则返回1。
		   int CurrentPos = Find (x);
		   if (LastFindOK ) return 0;						//该项在表中已经存在, 不再加入
		   ht[CurrentPos] = HashEntry ( x, Active );				//插入x
		   if ( ++CurrentSize < TableSize/2) return 1;				//当前已有项数加1, 不超过表长的一半返回
		   HashEntry *Oldht = ht;						//分裂空间处理: 保存原来的散列表
		   int OldTableSize = TableSize;
		   CurrentSize = 0;
		   TableSize = NextPrime ( 2 * OldTableSize );			//原表大小的2倍,取质数
		   AllocateHt ( );								//建立新的二倍大小的空表
		   for (int i=0; i<OldTableSize; i++)					//原来的元素重新散列到新表中
		      if ( Oldht[i].info == Active ) Insert ( Oldht[i].Element );	//递归调用
		   delete [ ] Oldht;
		   return 1;
		}

		template <class Type> int HashTable<Type>::IsIn ( const Type & x ) {
		//判断x是否在散列表中。若在表中, 则返回1, 否则返回0。
		   int CurrentPos = Find ( x );
		   return LastFindOK;
		}

		template <class Type> int HashTable<Type>::Remove ( const Type & x ) {
		//将x从散列表中删除。若删除成功, 则返回1, 否则返回0。
		   int CurrentPos = Find (x);
		   if (!LastFindOK ) return 0;						//该项在散列表中没有
		   ht[CurrentPos].info = Deleted;  return 1;				//作删除标记, 删除成功
		}



		//以下来自线性探查法
		template <class Type> void HashTable<Type>::MakeEmpty ( ) {		//清除散列表
		   for ( int i=0; i<TableSize; i++) ht[i].info = Empty;
		   CurrentSize = 0;
		}

		template <class Type> const HashTable<Type> & HashTable<Type>::operator= ( const HashTable<Type> &ht2 ) {
		//重载函数:复制一个散列表ht2
		   if ( this != &ht2 ) {
			 delete [ ] ht;  TableSize = ht2.TableSize;  AllocateHt ( );		//重新分配目标散列表存储空间
			 for ( int i=0; i<TableSize; i++ ) ht[i] = ht2.ht[i];			//从源散列表向目标散列表传送
			 CurrentSize = ht2.CurrentSize;						//传送当前表项个数
		   }
		   return *this;									//返回目标散列表结构指针
		}
      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -