汽车牌照课程设计报告Word文件下载.docx
《汽车牌照课程设计报告Word文件下载.docx》由会员分享,可在线阅读,更多相关《汽车牌照课程设计报告Word文件下载.docx(19页珍藏版)》请在冰豆网上搜索。
2.基数排序的过程
链式基数排序就是在链式存储结构下通过反复的分配、收集运算来进行排序的。
首先将待排序的记录分成若干个子关键字,排序时,先按最低位的关键字对记录进行初步排序;
在此基础上,再按次低位关键字进一步排序,以此类推,由低位到高位,由此关键字到主关键字,每一趟排序都在前一趟排序的基础上,直到按最高位关键对记录进行排序后,基数排序完成。
车牌号是由一个汉字、一个大写字母和五个数字组成,由于有34个省自治区简称,字母有26个,本来基数应该是34,但这样一来太麻烦,而且不好分析,故将汉字、字母转换为十进制数再进行基数排序,这样做的好处是,基数都是从0~9,比较简便,而且易懂。
为了更好的分析此算法,举一个例子:
一组记录的关键字为:
83,8,184,505,930,589,63,109,278
采用基数排序方法对其进行排序。
上述这组关键字的值都在0≦K≦99的范围内,我们可以把每一个数位上的十进制数字看成是一个关键字,即将关键字K看成由3个关键字K0,K1,K2组成。
其中,K0是百位上的数字,K1是十位上的数字,K2是个位上的数字。
因为十进制的基数是10,所以,每个数位上的数字都可能是0~9中的任何一个。
先按关键字K2来分配所有参与排序的元素,将K2=0的元素放在一组、K2=1的元素放在一组、……、K2=9的元素放在一组。
再按K2的值由0到9的顺序收集各组元素,形成序列(930,063,083,184,505,278,008,109,589,269)。
对上述序列中的元素再按关键字K1来分配,也分成10组。
然后再按K1的值由0到9的顺序收集各组元素,形成序列(505,008,109,930,063,269,278,083,184,589)。
对该序列中的元素再按关键字K0来分配。
然后按K0的值由0到9的顺序收集各组元素,形成序列(008,063,083,109,184,267,278,505,589,930)。
基数排序完成。
分析该例,可以看出基数排序的思想是:
在此基础上,再按次地位关键字进一步排序。
依次类推,由低位到高位,由次关键字到主关键字,每一趟排序都在前一趟排序的基础上,直到按最高位关键字对记录进行排序后,基数排序完成。
因此,在汽车牌照的基数排序中,首先将汽车牌照的汉字、字母全部转化为十进制数,以便于基数排序。
汉字和字母是由两个字符表示,转换好后方可进行基数排序。
接下来就是如何收集各组记录。
从上述例子可看出,各组记录的收集遵循“先进入该组的记录将先被收集”的原则可知,各组序列以列来描述较为精确。
因为要进行多次的分配与收集,为节省存储空间及运算方便,采用链队列来存储各组序列。
链队列的数量与基数一致,若基数为RAX,则令f[0]~f[RAX-1]分别指向RAX个链队列的队头节点,令r[0]~r[RAX-1]分别指向RAX个队列的队尾节点。
每次分配前,将RAX个链队列置空,即
for(i=0;
i<
RAX-1;
i++)
f[i]=r[i]=NULL;
Rnode*f[RAX],*r[RAX];
//*f[RAX],*r[RAX]分别为链队列的队头指针和队尾指针
longintelement[MAX];
//数组存储转换后的车牌号
主要算法:
1).数据录入函数
Rnode*SetList(Rnode*L,intn){
Rnode*p;
intm,j,k,i;
intt=0,count=1;
stringr;
L=NULL;
n;
{cout<
<
"
请输入第"
count<
个车主的所有信息"
endl;
cout<
cout<
车辆的车牌号是由一个汉字,一个大写字母和五个数字组成!
请输入该车的车牌号"
;
p=(Rnode*)malloc(sizeof(Rnode));
cin>
>
p->
key;
stringkey1=(string)p->
stringkey2=key1.substr(0,2);
for(t=0;
t<
=0;
t++){
for(j=0;
j<
N;
j++){
stringkey3=(string)a1[j];
//将汉字、字母转化为十进制数
if(key2==key3){
k=j;
}}
ints=k/10;
p->
keynum[0]=s;
s=k%10;
keynum[1]=s;
for(inth=0;
h<
K;
h++){
if(p->
key[2]==a2[h])
m=h;
}
s=m/10;
keynum[2]=s;
s=m%10;
keynum[3]=s;
for(intn=3;
n<
M-1;
n++){
intc=p->
key[n]-48;
keynum[n+1]=c;
……;
count++;
p->
next=L;
L=p;
returnL;
2).基数排序
若关键字为整型数据,则存放待排序记录的单链表可以这样构造:
#defineN8//N为待排记录的个数
Rnode*L,*p;
L=NULL;
//链表L初始化为空
for(i=1;
=N;
++i){//头插法建单链表L
p=malloc(sizeof(Rnode));
for(j=0;
=M-1;
++j)//分别输入M个子关键字
cin>
p->
next=L;
L=p;
}
voidDistribute(Rnode*L,inti){
Rnode*p;
intj,k;
for(k=0;
k<
=RAX-1;
k++)
f[k]=r[k]=NULL;
//将RAX个链队列初始化为空
p=L;
while(p!
=NULL){
L=L->
next;
j=p->
keynum[i];
//用记录中第i位关键字的值即为相应的队列号
if(f[j]==NULL)//将结点*p分配到相应的链队列f[i]中
f[j]=p;
else
r[j]->
next=p;
//队尾指针向后移动一位
r[j]=p;
r[j]->
next=NULL;
p=L;
Rnode*Collect()//从链队列f[0]开始,依次收集各链队列中的节点
{Rnode*L;
inti=0,j;
while(f[i]==NULL)i++;
//查找第一个不空的链队列
L=f[i];
for(j=i,k=i+1;
=RAX-1;
++k)
if(f[k]!
=NULL){r[j]->
next=f[k];
j=k;
returnL;
Rnode*paixu(Rnode*L)//排序函数
{Rnode*q;
inta=0;
q=L;
for(inti=M-1;
i>
i--){
Distribute(L,i);
L=Collect();
……}
到此基数排序算法结束。
从算法中容易看出,对于n个记录(每个记录含M个子关键字,每个子关键字的取值范围为RAX个值)进行链式排序的时间复杂度为O(M(n+RAX)),其中每一趟分配算法的时间复杂度为O(n),每一趟收集算法的时间复杂度为O(RAX),整个排序进行M趟分配和收集,所需辅助空间为2×
RAX个队列指针。
当然,由于需要链表作为存储结构,则相对于其它以顺序结构存储记录的排序方法而言,还增加了n个指针域空间。
3)二分查找的算法思想
当汽车牌照号都转换为数字形式后,需要用一个longintelement[MAX]进行存储,以便进行查找。
(1.)将表中间位置记录的关键字与给定K值比较,如果两者相等,则查找成功。
(2)、如果两者不等,利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于给定K值,则进一步查找前一子表,否则进一步查找后后一子表。
(3)、重复以上过程,直到找到满足条件的记录,则查找成功,或者直到分解出的子表不存在为止,此时查找不成功。
例如对一有序的数组a(1,2,3,4,5,6,7,8,9)进行查找数key=6;
首先定义low=0,high=8,mid=(low+high)/2=4;
第一步:
将a[mid]与key比较,我们发现a[mid]<
key,令low=mid+1=5;
mid=(low+high)/2=6;
第二步:
将a[mid]与key比较,我们发现a[mid]>
key,此时再令high=mid-1=5;
mid=(low+high)/2=5;
第三步:
将a[mid]与key比较,此时a[mid]=key,查找结束,返回mid;
第四步:
如果仍未找到,则继续进行,直到low>
high,此时返回-1,查找失败;
对于该程序最严重的问题就是如何对链表进行二分查找,经过查找资料以及思考,要想纯粹的输入一个车牌号不做相应的变换就进行查找,这种思路虽然很清晰,但运行起来不太方便,因为这不仅要对数字进行查找,而且还对汉字、字母进行查找。
因此,这种思路不合理。
最后,我想到用一个长整型的数组来存储变换后的车牌号,对这组车牌号再进行相关查找和相关操作,最后具体实现。
该部分的具体代码为:
returnL;
intTwsearch(Rnode*L,longintkey,intlow,inthigh)//递归二分查找算法
{
intmid;
if(low>
high)
return-1;
else{
mid=(high+low)/2;
if(element[mid]==key)
returnmid;
elseif(key<
element[mid])
return(BinSrch(L,key,low,mid-1));
return(BinSrch(L,key,mid+1,high));
voidsearch(Rnode*L)//将要查找的车牌号转换为十进制数
intk,m;
chard[8];
longints;
d;
stringkey1=(string)d;
for(intg=0;
g<
g++){
for(intj=0;
if(key2==key3)
k=j;
s=k/10*100000000+k%10*10000000;
if(d[2]==a2[h])
m=h;
s=s+m/10*1000000+m%10*100000;
s=s+((longint)d[3]-48)*10000+((int)d[4]-48)*1000+((int)d[5]-48)*100+((int)d[6]-48)*10+(int)d[7]-48;
intc=BinSrch(p,s,0,b);
if(c==-1)
cout<
抱歉,没有您要查找的记录!
endl<
else{
查找成功,此车的详细信息为:
车主"
"
车牌号"
车色"
车型"
for(inti=0;
c;
i++){
p=p->
name<
key<
color<
type<
}}
cout<
四.上机调试
刚开始着手做这个程序的时候,因为对数进行基数排序,我还以为很好做,但是要进行汉字、字母和数字混排的数进行基数排序,不知道该如何进行处理,修改多次程序都不能正确满足要求,最后,通过查找资料,可以把汉字、字母转换为十进制数在进行基数排序,最后得以实现。
在进行基数排序时,由于基数排序算法在书本中有详细介绍,因此没有出现太大的问题。
在调试过程中若输入的车辆牌照有皖A12345,但在查找此车牌号时确显示没有您要查找的记录,经过一步一步的调试发现输入要查找的车牌号是存储在一个一维字符数组中的,例如chara=‘3’,使用强制类型转换intb=(int)a,得到的b是等于51的。
这是因为一个数字以字符形式存储和以整型数据存储它们的ASCII码是不同的。
只要将上述的强制类型转换语句改为intb=(int)a-48即可得到正确的结果,此问题得以解决。
在实现车辆信息查找时,如果在查找前并没有进行排序,不会输出结果的。
因此,在进行查找时,先进行排序,这样一来很麻烦了。
经过修改,将排序函数直接加到查找函数中,这样不管怎么样,都排序了。
五.测试结果及其分析
1.添加车辆
首先会提示输入要添加的车辆数
2.选择你要执行的菜单功能3
3.退出
六.用户使用说明
按提示操作,首先将弹出一个菜单,按提示输入你要执行的菜单功能,选择1,添加车辆,会提示添加的车辆数,再按提示输入相关数据信息,输入结束后,会提示一行字,flag=0,继续操作,否则退出。
选择flag=0,继续执行菜单功能,选择2,进行排序,选择3,按车牌号进行查找,选择4,是输出所有车辆信息,5退出程序。
七.参考文献
1.王昆仑、李红主编.数据结构与算法.出版地:
中国地道出版社,2007年
2.李红、王昆仑主编.“数据结构与算法”设计指导2009年
2.郑莉等著.C++语言程序设计(第三版).北京:
清华大学出版社,2003.
八.附录
源代码:
#include"
stdio.h"
iostream"
malloc.h"
string"
#defineNULL0
usingnamespacestd;
#defineM9//关键字的个数
#defineN34//省市自治区的个数
#defineK26//大写字母的个数
#defineRAX10//基数的个数
#defineMAX100//最大能够处理的车辆数
stringa1[N]={"
澳"
"
川"
鄂"
甘"
赣"
港"
贵"
桂"
黑"
沪"
吉"
津"
晋"
京"
辽"
鲁"
闽"
内"
宁"
青"
琼"
山"
陕"
苏"
台"
皖"
湘"
新"
冀"
渝"
豫"
云"
藏"
浙"
};
chara2[K]={'
A'
'
B'
C'
D'
E'
F'
G'
H'
I'
J'
K'
L'
M'
N'
O'
P'
Q'
R'
S'
T'
U'
V'
W'
X'
Y'
Z'
Rnode*f[RAX],*r[RAX];
//*f[RAX],*r[RAX]分别为链队列的队头指针和队尾指针
intb;
//汽车牌照转换为数字后最后一个汽车牌照的数组中的下标
cout<
请输入该车的颜色:
cin>
color;
请输入该车的车型:
type;
请输入该车的车主姓名:
name;
if(f[j]==NULL)
Rnode*Collect()
{Rnode*L;
inti=0,j,k;
while(f[i]==NULL)
i++;
L=f[i];
for(j=i,k=i+1;
if(f[k]!
next=f[k];
j=k;
intTwsearch(Rnode*L,longintkey,intlow,inthigh){
return(Twsearch(L,key,low,mid-1));
return(Twsearch(L,key,mid+1,high));
voidsearch(Rnode*L){