机试算法讲解: 第10题 让我们来查询学生的信息

/*
问题:输入N个学生的信息,进行查询
输入:
4
01 李江 男 21
02 刘唐 男 23
03 张军 男 19
04 王娜 女 19
5
02
03
01
04
03
输出:
02 刘唐 男 23
03 张军 男 19
01 李江 男 21
04 王娜 女 19
03 张军 男 19
N;学生个数,<=1000,
M,查询M次,M<=10000

时间复杂度:
普通搜索:O(n*m) = O(1000*10000)=O(10000000),千万数量级
二分搜索:以学号为搜索主题,O(log2N*M)(搜索) + O(log2N*N)(排序) =O(10*10000) + O(10*1000)=O(100000),十万级

关键:
1 二分查找的查询条件 是 while(low <= high),=号不能丢掉,因为有时候low = high时,才找到目标值
2 使用二分查找的前提条件是,有序排列,为此可以使用快速排序进行排序(你没有做)
3 性别虽然是一个汉字,但是至少需要2个字节,因此存储类型必须用字符指针
*/

#include <stdio.h>
#include <stdlib.h>

typedef struct StuInfo
{
	bool operator < (StuInfo& stuInfo)
	{
		return _iStuNo < stuInfo._iStuNo;
	}
	int _iStuNo;
	char _sName[32];
	char _sSex[6];//关键性别如果是汉字,至少2个字节,但是char只有1个字节
	int _iAge;
}StuInfo;

template<typename T>
int partition(T* A,int low ,int high)
{
	T iPos = A[low];
	while(low < high)
	{
		while(low < high && iPos < A[high])
		{
			high--;
		}
		A[low] = A[high];
		while(low < high && A[low] < iPos)
		{
			low++;
		}
		A[high] = A[low];
	}
	A[low] = iPos;
	return low;
}

template<typename T>
void quickSort(T *A,int low,int high)
{
	if(low < high)
	{
		int iPos = partition(A,low,high);
		quickSort(A,low,iPos - 1);
		quickSort(A,iPos + 1,high);
	}
}

//int binarySearch(int *Array,int iLow,int iHigh,int iSeaValue)
int binarySearch(int *Array,int iLow,int iHigh,int iSeaValue)
{
	int iMid;
	while(iLow <= iHigh)//易错,这边要加等号,否则low=high不循环了
	{
		iMid = (iLow + iHigh)/2;
		if(iSeaValue < Array[iMid])
		{
			iHigh = iMid - 1;
		}
		else if(iSeaValue > Array[iMid])
		{
			iLow = iMid + 1;
		}
		else
		{
			return iMid;
		}
	}
	//程序走到这里,表示没有找到
	return -1;
}

int main(int argc,char* argv[])
{
	int N;
	//while(EOF!=scanf("%d %s %c %d",&stuInfo.iStuNo,stuInfo.sName,stuInfo.cSex,stuInfo.iAge))
	while(EOF!=scanf("%d",&N) && N <= 1000)
	{
		StuInfo stuInfo[100];
		int iGivStuNo[100],i;
		
		//输入N个学生的信息
		for(i = 0; i < N ;i++)
		{
			scanf("%d %s %s %d",&stuInfo[i]._iStuNo,stuInfo[i]._sName,stuInfo[i]._sSex,&stuInfo[i]._iAge);//字符串不需要取地址符,字符需要取地址符,又是取地址符没加
			//iGivStuNo[i] = stuInfo[i]._iStuNo;
			//printf("\n");
		}

		//对输入的学生信息按照学号进行快速排序
		quickSort<StuInfo>(stuInfo,0,N-1);
		//将已经排好序的学号存入数组
		for(i = 0; i < N ;i++)
		{
			iGivStuNo[i] = stuInfo[i]._iStuNo;
		}

		int M;
		scanf("%d",&M);
		if(M > 10000)
		{
			break;
		}
		else
		{
			int iStuNoArr[100];
			int iStuNo,j;
			for(j = 0;j < M;j++)
			{
				scanf("%d",&iStuNo);
				iStuNoArr[j] = iStuNo; 
			}

			//下面用二分法进行查找
			for(j = 0; j < M ; j++)
			{
				int iRes = binarySearch(iGivStuNo,0,N-1,iStuNoArr[j]);
				if(iRes==-1)
				{
					printf("%s","No Answer!");
				}
				else
				{
					printf("%d %s %s %d\n",stuInfo[iRes]._iStuNo,stuInfo[iRes]._sName,stuInfo[iRes]._sSex,stuInfo[iRes]._iAge);
				}
			}
		}
	}
	system("pause");
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值