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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

单链表的应用(电话本)

發布時間:2024/7/5 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单链表的应用(电话本) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

單鏈表

單鏈表的定義就不說了, 很簡單, 請自行百度; 那么從今天的主題<單鏈表的應用>入手; 利用單鏈表實現電話本的模擬程序:定義單鏈表的數據類型,將頭插法和尾插法、插入、逆置、刪除、查找、修改、計數、輸出等操作都定義成子函數的形式,最后在主函數中調用它( 兄弟們調用就不弄了, 自行測試, 增加動手能力 )
整個程序最主要的步驟還是插入, 查找, 刪除操作, 其他操作都可以圍繞這三個操作來進行, 其實單鏈表無論是什么操作都可以總結為指針的操作, 無非是指針的指向, 通過指針的指向就能完成很多步驟, 但是在單鏈表中由于指針是單向的, 不像雙鏈表那樣可以雙向操作, 所以操作起來有點不太方便(其實還是很簡單的, 只是說了嚇唬人的)
此處做注釋: 鏈表的head節點數據域不存數據, head所在的位置是-1, 鏈表中元素是從0號開始
那么我就先從insert開始:

insert操作
void insert(int index,LNode *L1,LNode *L2);
insert就是在特定的位置(index)把L2節點連接到L1上面, 所以就有如下實現方式:

void insert(int index,LNode *L1,LNode *L2){for(int i=0;(i<index)&&(L1!=NULL)&&(L2!=NULL);i++,L1=L1->next);L2->next=L1->next;L1->next=L2; }

L1與L2需要判斷是否為空(避免引用非法指針), 上面的for操作主要是將指針L1移動到需要插入的位置的前一個位置, 首先將L2的next指針存入原本L1的后一個位置的地址, 然后將L1的next指針存入L2的地址, 這兩步操作不能顛倒, 顛倒, 原本鏈表中L1后面部分的鏈表結構將會丟失; (請細細理解)
在創建鏈表的過程中我們可以選擇頭插法或者尾插法進行創建鏈表;
所謂頭插法簡單的來說就是每次插入操作總是把插入節點的位置定位0號, 頭插法的意義就在于我們可以很容易完成逆置的操作, 頭插法代碼如下:

void insertHead(LNode *L1,LNode *L2){insert(0,L1,L2); }

頭插法就是在0號位置把L2插入到L1的后面, 如果將頭插法應用到創建鏈表, 那么此處的L1便是head

尾插法就是每次在尾部插入節點, 插入的位置總是末尾; 代碼如下:

void insertTail(LNode *L1,LNode *L2,int t){insert(t,L1,L2); }

此處L1, L2的含義與頭插法中的含義一致, t表示末尾的位置, 末尾需要傳入參數來確定, 待會在main函數中測試再進行說明, 兩個插入的區別就在于位置的變化, 由兩種插入方面所形成的鏈表順序是相反的

逆置操作
上面提到逆置操作需要用到頭插法, 因為每次節點傳入的insertHead中, 我總是把節點插入到0號位置, 也就是head后面, 一個正序的鏈表, 我把它的節點按順序不斷拆下來, 同時將每個拆下來的節點連接到head的0號位上面, 而不是又按照原有的順序進行順序連接(表面上看好像連和沒連一樣, 這里你需要畫圖好好思考), 舉個例子: head 0 1 2 3的順序表, 0拆下連接到head上面, 1拆下連接到head上面, 此時0就連接到1號上面, 順序為head 1 0, 同理, 2拆下連接到head上面, 1又連接到2上面, 順序為head 2 1 0 ,最后整個過程重復, 得到的順序就是head 3 2 1 0, 然后就可以做到把一個正序的鏈表變為逆序的
話不多說, 上代碼:

void convert(LNode *L){//此處逆置是對整個鏈表逆置, L傳入的是headLNode* p=L->next;L->next=NULL;LNode* q;int t_size=size;while(t_size>0){q=p->next;p->next=NULL;insert(0,L,p);p=q;t_size--;} }

LNode* p=L->next;L->next=NULL;LNode* q;是將head分離, while內部的操作主要是通過不斷迭代的方式, 做到將第一個節點與第二個節點進行分離, 以達到將在0號位插入的效果

刪除, 查找, 修改
這三步操作是圍繞查找來, 由于單鏈表結構的特點, 所以只能做到順序查找(可采用平衡二叉搜索樹, 實現鏈表的O(logn)的復雜度)
上代碼:

LNode *find(LNode *L,char *e){while(L!=NULL){//避免引用非法指針if(strcmp(L->data.name,e)==0)return L;L=L->next;}return head; }

傳入head節點, 以及所要查找的元素e(使用指針, 其效果與char e[]一致), 不斷比較, 成功則返回所指向的節點, 失敗則返回head

刪除: 刪除我做了修改, 讓它具有兩個功能–刪除特定元素, 刪除整個鏈表(其實還是為了偷懶, 少寫代碼)

void remove(LNode *L,LNode *LTarget_value){while(L->next!=NULL){if((L->next==LTarget_value)&&(LTarget_value!=NULL)){//用于刪除特定元素LNode* p=L->next;L->next=p->next;//將所要刪除的節點進行分離操作size--;//刪除一個人就需要總人數減一次delete p;return;//若刪除p立馬退出 }else if(LTarget_value==NULL){//用于刪除整個鏈表LNode* p=L->next;L->next=p->next;delete p;//分離一個節點進行一次刪除,直到刪除到只剩下head節點才停止}if(LTarget_value!=NULL) L=L->next;//只有在刪除特定元素的時候才進行L的移動 }if(LTarget_value==NULL) delete L;//只有在刪除整個鏈表才刪除head }

修改操作: 修改可針對特定元素, 此處只做簡單說明
上代碼:

void revise(LNode *L,char *e,char *Ae,int i){LNode *p=find(L,e);if(p->data.name==NULL && p->data.num=NULL )return;//表示沒有找到要修改的元素,p現在是head,head里面沒有存數據, 直接跳出程序if(i==1) strcpy(p->data.name,Ae);else if(i==2) strcpy(p->data.num,Ae); }

L表示head, e表示要查找的目標元素, Ae表示替換e, i表示選擇替換name, 還是替換num

輸出
輸出就很簡單了, 不做敘述

void display(LNode *L){while(L!=NULL){printf("%s %s\n",L->data.name,L->data.num);L=L->next;} }

此次測試所用的結構體

struct DataType{char name[10];char num[12]; }; struct LNode{LNode *next;DataType data; };

兩個全局變量

LNode *head=new LNode();//head節點 int size=0;//用作計數, 計算存入多少聯系人

main函數 的測試代碼

int main(){int t_size;int sum=0,i;char na[10],nu[12]; printf("輸入需要創建的電話本大小以及1.頭插OR2.尾插\n");scanf("%d%d",&t_size,&i);while(sum<t_size){printf("輸入名字,號碼\n");fflush(stdin);scanf("%s%s",na,nu);LNode *s=new LNode();s->next=NULL;strcpy(s->data.name,na);strcpy(s->data.num,nu);size++; //每輸入一次,size進行一次增加, 只有在輸入才有人數的增加if(i==1){//輸入時選擇頭插法,還是尾插法insertHead(head,s);}else if(i==2){insertTail(head,s,sum);}++sum;}display(head); // printf("輸入要查找的元素\n");fflush(stdin); // scanf("%s",na); // printf("%s\n",find(head,na)->data.name); // printf("刪除鏈表中元素\n");fflush(stdin); // scanf("%s",na); // if(i==1){ // puts("輸入要刪除的元素");scanf("%s",na); // remove(head,find(head,na)); // } // display(head); // puts("若號碼以及名字都要修改那么你可選擇直接刪除"); // puts("需要修改的元素,修改后的值,1.修改名字,2.修改號碼"); // scanf("%s%s%d",na,nu,&i); // revise(head,na,nu,i);puts("輸入在幾號位置進行插入操作,插入元素為,0號是首元素");scanf("%d",&i);printf("輸入名字,號碼\n");fflush(stdin);scanf("%s%s",na,nu);LNode *s=new LNode();s->next=NULL;strcpy(s->data.name,na);strcpy(s->data.num,nu);insert(i,head,s); // convert(head);display(head);remove(head,NULL); return 0; }

代碼進行拼湊就可使用, 可能存在異常, 但是主要還是闡述思想, 上面注釋部分為測試每個功能的代碼, 最后還需做修改, 寫的不好, 還有很多地方需要改進, 就不做修改了, 界面做的很簡陋, 整個程序最核心的還是insert, find, remove, 理解頭插法與尾插法的區別, 有問題還請在下方留言

總結

以上是生活随笔為你收集整理的单链表的应用(电话本)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。