日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

通讯录的简单制作

發(fā)布時間:2023/12/14 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通讯录的简单制作 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

今年的小學期算法課設抽到了通訊錄制作的題目,用了兩三天和隊友一起完成,整體沒有用到什么難以理解的算法,僅僅是用到了快速排序和折半查找。目的是在此記錄一下,給需要的同學們一點參考。

目錄

基本描述

初步思路

核心代碼

記錄姓名屬性的首字母提取

插入新紀錄

鏈表記錄的保存

本地txt文件導入鏈表

其他模塊

結束語


基本描述

(1)算法目標:

?? 通訊錄插入時能夠有效率的插入并按姓氏字母順序排序。

(2)數(shù)據(jù)輸入:

?? 用戶輸入指令。

?? Enter:向鏈表中插入一條新的紀錄;

?? Display:顯示一條記錄;

?? Search:查找一條記錄;

?? Delete:刪除一條記錄;

?? Save:將當前鏈表中的記錄寫入txt文件保存本地;

?? Load:將本地txt文件中的記錄載入鏈表;

(3)數(shù)據(jù)輸出:

?? Display:輸出顯示的記錄

?? Search:輸出查找的記錄

typedef struct person {string name;string street;string city;string state;string EIP; struct person *prior, *next; } singlePerson;//通訊錄個體Node typedef struct addressList {singlePerson *head;singlePerson *end;int length; } addressList;//通訊錄雙向鏈表

初步思路

? ? ? ?數(shù)據(jù)結構采用雙向鏈表的結構來儲存用戶輸入的個體信息,插入時采取按照輸入信息中的名字首字母順序進行排序,插入時查找插入位置采取分治法中的二分法進行查找;載入文件時先將文件中的記錄導入鏈表,再采用快速排序的方法進行鏈表的排序。

核心代碼

記錄姓名屬性的首字母提取

void get_first_letters(string szChinese,char piyinBuf[],const unsigned int maxBufLen,unsigned int &piyinBufLen) {unsigned char chr[3];piyinBufLen = 0;unsigned int chineseLen = szChinese.size();for (unsigned int i = 0; i < chineseLen && piyinBufLen < maxBufLen; ++i){unsigned char c = szChinese[i];// 排除askii 碼if (isascii(c)){piyinBuf[piyinBufLen++] = c;}else{chr[0] = szChinese[i];chr[1] = szChinese[++i];chr[2] = 0;wchar_t wchr = 0;wchr = (chr[0] & 0xff) << 8;wchr |= (chr[1] & 0xff);piyinBuf[piyinBufLen++] = toupper(get_first_letter(wchr));}} }bool between(wchar_t start,wchar_t end,wchar_t aim) {if (start <= aim && aim <= end){return true;}return false; }char get_first_letter(wchar_t wchar) {if (between(0xB0A1,0xB0C4,wchar)) return 'a';if (between(0XB0C5,0XB2C0,wchar)) return 'b';if (between(0xB2C1,0xB4ED,wchar)) return 'c';if (between(0xB4EE,0xB6E9,wchar)) return 'd';if (between(0xB6EA,0xB7A1,wchar)) return 'e';if (between(0xB7A2,0xB8c0,wchar)) return 'f';if (between(0xB8C1,0xB9FD,wchar)) return 'g';if (between(0xB9FE,0xBBF6,wchar)) return 'h';if (between(0xBBF7,0xBFA5,wchar)) return 'j';if (between(0xBFA6,0xC0AB,wchar)) return 'k';if (between(0xC0AC,0xC2E7,wchar)) return 'l';if (between(0xC2E8,0xC4C2,wchar)) return 'm';if (between(0xC4C3,0xC5B5,wchar)) return 'n';if (between(0xC5B6,0xC5BD,wchar)) return 'o';if (between(0xC5BE,0xC6D9,wchar)) return 'p';if (between(0xC6DA,0xC8BA,wchar)) return 'q';if (between(0xC8BB,0xC8F5,wchar)) return 'r';if (between(0xC8F6,0xCBF0,wchar)) return 's';if (between(0xCBFA,0xCDD9,wchar)) return 't';if (between(0xCDDA,0xCEF3,wchar)) return 'w';if (between(0xCEF4,0xD188,wchar)) return 'x';if (between(0xD1B9,0xD4D0,wchar)) return 'y';if (between(0xD4D1,0xD7F9,wchar)) return 'z';return '\0'; }

此處參考了https://blog.csdn.net/wangkr111/article/details/7952085的方法并對輸入的類型進行了稍微的調(diào)整。具體的原理各位可以移步鏈接去研究一下關于漢字的區(qū)位碼的計算。

但是注意!這個方法僅僅適用于一般的常用漢字!這個方法對于稍微生僻一點的字無效!

插入新紀錄

插入新紀錄運用的方法是按照姓名首字母的順序來進行插入位置的查找并進行雙向鏈表的插入。

int find_enter_pos(addressList &record,singlePerson *elem){int low=0,high=record.length-1;int mid;char* k=get_pinyin(elem);singlePerson *Mid_elem;char *r;while(low<=high){Mid_elem=record.head;mid=(low+high)/2;for(int i=0;i<mid;i++){Mid_elem=Mid_elem->next;}r=get_pinyin(Mid_elem);if(strcmp(k,r)<0) {high=mid-1;}else if(strcmp(k,r)>0) {low=mid+1;}}return low; } char * get_pinyin(singlePerson *elem){char *buf=new char[1024];for(int i=0;i<1024;i++){buf[i]='\0';}unsigned int len = 0;string a=elem->name;get_first_letters(a,buf,1024,len);return buf; }

尋找插入位置時運用了折半查找,針對具體的需求對傳統(tǒng)的折半查找做了相應的修改。找到插入位置后進行雙向鏈表新紀錄的插入即可,這里不再詳述。

鏈表記錄的保存

void save(const addressList &record) {singlePerson *elem=record.head;string cache;cin>>cache;//文件路徑輸入 const char *p = cache.c_str();ofstream OutFile(p);if(!OutFile) cout<<"Error";else{string str=" ";while(elem!=NULL){string temp=elem->name+str+elem->street+str+elem->city+str+elem->EIP+str+elem->state;OutFile << temp;OutFile <<endl;elem=elem->next;}cout<<"保存成功,路徑:"<<cache<<endl; OutFile.close();} }

本地txt文件導入鏈表

void load(addressList &record) {singlePerson *elem;string cache;cin>>cache;//文件路徑輸入 const char *p = cache.c_str();ifstream fin(p); string s; string str=" ";vector<vector<string> > info;vector<string> _info;if(!fin) cout<<"No such File!"<<endl;else{while( getline(fin,s) ) { int pos=s.find(str);while(pos!=s.npos){_info.push_back(s.substr(0,pos));s=s.substr(pos+1,s.size());pos=s.find(str);}_info.push_back(s);info.push_back(_info);_info.clear(); } for(int i=0;i<info.size();i++){elem=new singlePerson;elem->name=info[i][0];elem->street=info[i][1];elem->city=info[i][2];elem->EIP=info[i][3];elem->state=info[i][4];if(record.head==NULL){record.head=elem;record.head->next=elem;record.head->prior=elem;record.end=record.head;} else{record.end->next=elem;elem->prior=record.end;record.end=elem;elem->next=NULL;}record.length++;}elem=record.head;QuickSort(record,0,record.length-1); cout<<"載入成功!"<<endl; }fin.close(); }

這里將一個Tab鍵作為分隔符,將文件中的每行記錄進行分割,并保存至vector容器中(為了方便插入和清空),最后一并插入鏈表中,最后對鏈表進行快速排序。

vector<char*> get_rbuf(const addressList &record) {singlePerson *elem=record.head;vector<char* > rbuf;int t=0;elem=record.head;while(elem!=NULL){char *buf=new char[1024];for(int i=0;i<1024;i++){buf[i]='\0';}unsigned int len = 0;string szChinese = elem->name;get_first_letters(szChinese,buf,1024,len);strlwr(buf);rbuf.push_back(buf); t++;elem=elem->next; }return rbuf; } void exchange(singlePerson *a,singlePerson *b){singlePerson *elem=new singlePerson;elem->name=a->name;elem->street=a->street;elem->city=a->city;elem->state=a->state;elem->EIP=a->EIP;a->name=b->name;a->street=b->street;a->city=b->city;a->state=b->state;a->EIP=b->EIP;b->name=elem->name;b->street=elem->street;b->city=elem->city;b->state=elem->state;b->EIP=elem->EIP; } int Partition(addressList &record,vector<char *> buf,int first,int end){int i=first,j=end;int m;singlePerson *head=record.head;for(m=0;m<first;m++){head=head->next;}singlePerson *tail=record.head;for(m=0;m<end;m++){tail=tail->next;}singlePerson *elem;while(i<j){while(i<j&&strcmp(buf[i],buf[j])<=0){j--;tail=tail->prior;}if(i<j){exchange(head,tail);buf=get_rbuf(record);head=head->next;i++;}while(i<j&&strcmp(buf[i],buf[j])<=0){i++;head=head->next;}if(i<j){exchange(head,tail);buf=get_rbuf(record);tail=tail->prior;j--;}}return i; } void QuickSort(addressList &record,int first,int end){int pivot;if(first<end){pivot=Partition(record,get_rbuf(record),first,end);QuickSort(record,first,pivot-1);QuickSort(record,pivot+1,end);} }

參考傳統(tǒng)的快速排序,這里get_rbuf函數(shù)返回的是當前鏈表所有記錄姓名屬性的首字母數(shù)組;partiton函數(shù)以get_rbuf返回的數(shù)組為依據(jù)對鏈表進行劃分,這里注意拼音數(shù)組的下標和鏈表的對應關系;最后進行迭代即可。

其他模塊

因為其他模塊,像查找、刪除等都是雙向鏈表的基本操作,在這里就不進行詳述了。

結束語

因為能力有限,做出來的東西瑕疵肯定很多,但是還是要本著分享的精神將我們覺得有意義、值得大家討論的東西貼出來供大家參考。如有什么有問題的地方可以盡情指出。

總結

以上是生活随笔為你收集整理的通讯录的简单制作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。