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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

第六天2017/04/11(1:结构体链表基础和相关经典操作)

發(fā)布時(shí)間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第六天2017/04/11(1:结构体链表基础和相关经典操作) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、結(jié)構(gòu)體基礎(chǔ)

【知識(shí)回顧】自定義數(shù)據(jù)結(jié)構(gòu)的本質(zhì)

//結(jié)構(gòu)體中有結(jié)構(gòu)體變量、結(jié)構(gòu)體指針 #include "stdio.h" #include "stdlib.h" #include "string.h"struct student {char name[64];int age;char *p; };struct teacher {char name[64];int age;char *p;struct student s1; //老師結(jié)構(gòu)體中有學(xué)生結(jié)構(gòu)體變量struct student *pstu;struct teacher *ptea; };//struct teacher //這種定義數(shù)據(jù)類型的方法是錯(cuò)誤的,因?yàn)榫幾g器不知道 //{ //這種數(shù)據(jù)類型所占內(nèi)存的大小 // struct teacher tea; //};int main() {struct teacher t1;struct student s2;t1.age = 40;t1.s1.age = 24; //我們想通過(guò)pstu去操作pstu所指向的內(nèi)存空間,但是這個(gè)內(nèi)存空間不存在。 //但是沒(méi)有內(nèi)存哪有指針!//t1.pstu->age = 20; //沒(méi)有內(nèi)存哪有指針? //正確的使用方法,見下t1.pstu = &s2; //先讓pstu指向?qū)W生變量s2t1.pstu->age = 20; //在進(jìn)行賦值strcpy(t1.pstu->name,"guojiawei");printf("%d,%s\n",t1.pstu->age,t1.pstu->name);getchar(); }

二、鏈表
鏈表的學(xué)習(xí)目錄

鏈表圖

//【綜合示例】鏈表的創(chuàng)建、打印、插入、刪除、銷毀、逆置#include "stdio.h" #include "stdlib.h" #include "string.h"typedef struct Node {int data;struct Node *next; }SLIST;//函數(shù)的聲明 int create_SList(SLIST** Head) ; int SList_print(SLIST* pHead); int SList_Insert(SLIST* pHead,int x,int y); int SList_Delete(SLIST* pHead,int y); int SList_Destroy(SLIST* pHead); int SList_Reverse(SLIST* pHead); //鏈表的逆置int main() {SLIST *pHead = NULL;if(create_SList(&pHead) != 0)return -1;printf("打印鏈表:");SList_print(pHead);//在值為x的結(jié)點(diǎn)后面插入值為y的結(jié)點(diǎn)int x ;int y ;printf("輸入要查找結(jié)點(diǎn)為 x 的值 ");scanf("%d",&x);printf("輸入要插入的值 y = ");scanf("%d",&y);if(SList_Insert(pHead,x,y) != 0){return -1;}printf("在值為x的結(jié)點(diǎn)后面插入值為y的結(jié)點(diǎn)后,打印鏈表:\n");SList_print(pHead); //刪除結(jié)點(diǎn)為y的鏈表結(jié)點(diǎn)int rv;printf("輸入要?jiǎng)h除的值 y = ");scanf("%d",&y);rv = SList_Delete(pHead,y);if(rv == 0){printf("找到值為y的點(diǎn),刪除的值為y的結(jié)點(diǎn)后,打印鏈表:\n");SList_print(pHead);}else{printf("沒(méi)找到值為y的點(diǎn),直接打印鏈表:\n");SList_print(pHead);} //鏈表的逆置SList_Reverse(pHead);printf("鏈表逆置后,打印鏈表:");SList_print(pHead);//銷毀鏈表SList_Destroy(pHead);getchar(); }//創(chuàng)建鏈表 int create_SList(SLIST** Head) //用二級(jí)指針作形參,傳入的實(shí)參是一級(jí)指針的地址 {int ret = 0;int data = 0;//1.建立頭結(jié)點(diǎn)并初始化SLIST *pHead = (SLIST*)malloc(sizeof(SLIST));if(pHead==NULL){ret = -1;printf("func create_SList() err:%d",ret);return ret;}pHead->data = 0;pHead->next = NULL;//2.循環(huán)創(chuàng)建結(jié)點(diǎn),結(jié)點(diǎn)數(shù)據(jù)域中的數(shù)值從鍵盤輸入,以輸入值為-1結(jié)束輸入SLIST *pCur = NULL; //當(dāng)前指針:輔助指針pCur = pHead; //準(zhǔn)備環(huán)境,讓pCur指向pHeadprintf("請(qǐng)輸入數(shù)據(jù):(-1:輸入完畢)\n");scanf("%d",&data);while(data !=-1){SLIST *pNew = (SLIST*)malloc(sizeof(SLIST));if(pNew == NULL){ret = -2;SList_Destroy(pHead); //很重要:能防止內(nèi)存泄漏printf("func:create_SList() err malloc:%d",ret);return ret;}pNew->data = data;//①新結(jié)點(diǎn)入鏈表pCur->next = pNew; pNew->next = NULL;//②當(dāng)前結(jié)點(diǎn)指針pCur下移(新結(jié)點(diǎn)變成當(dāng)前結(jié)點(diǎn))pCur = pNew;printf("請(qǐng)輸入數(shù)據(jù):(-1:輸入完畢)\n");scanf("%d",&data);}*Head = pHead; //二級(jí)指針作輸出的模型return ret; }//打印鏈表 int SList_print(SLIST* pHead) {if(pHead == NULL)return -1;SLIST* pCur = NULL;pCur = pHead->next; //準(zhǔn)備環(huán)境while(pCur){printf("%7d",pCur->data);pCur = pCur->next;}printf("\n");return 0; }//在x結(jié)點(diǎn)后插入值為y的結(jié)點(diǎn);如果x結(jié)點(diǎn)不在,就把y結(jié)點(diǎn)插入到表尾 int SList_Insert(SLIST* pHead,int x,int y) {int ret = 0;if(pHead == NULL) //如果無(wú)頭結(jié)點(diǎn),則error{ret = -1;printf("func:SList_Insert error %d",ret);return ret;} //---------------------------------------------------------------- //若有頭,則在該鏈表中查找值為x的結(jié)點(diǎn)//環(huán)境準(zhǔn)備SLIST* pPre = pHead;SLIST* pCur = pHead->next;SLIST* pTmp = NULL;while(pCur!=NULL){if(pCur->data == x) //如果找到了x{break;}//如果沒(méi)找到x,重置pPre、pCur的位置(把它倆的位置后移一個(gè)位置),繼續(xù)下一次while循環(huán)pPre = pCur;pCur = pCur->next;} //while循環(huán)完成后,有下面兩種情況:一種是查找到x的結(jié)點(diǎn);一種是沒(méi)查找到x結(jié)點(diǎn)//case1:若沒(méi)查找到x結(jié)點(diǎn)(則此時(shí)pPre指向鏈表的最后一個(gè)結(jié)點(diǎn); pCur指向最后一個(gè)結(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)即空結(jié)點(diǎn))if(pCur == NULL){pCur = (SLIST*)malloc(sizeof(SLIST));if(pCur == NULL){ret = -2;printf("func:SList_Insert error: malloc %d",ret);SList_Destroy(pHead);return ret;}pCur->data = y;pPre->next = pCur;pCur->next = NULL;}else //如果沒(méi)有找到值為x的結(jié)點(diǎn):此時(shí)pCur指向值為x的結(jié)點(diǎn),pPre指向值為x結(jié)點(diǎn)的前驅(qū){SLIST* pNew = (SLIST*)malloc(sizeof(SLIST));if(pNew == NULL){ret = -2;printf("func:SList_Insert error: malloc %d",ret);SList_Destroy(pHead);return ret;}pNew->data = y;pNew->next = pCur;pPre->next = pNew;}return ret; }//刪除值為y的結(jié)點(diǎn) int SList_Delete(SLIST* pHead,int y) { //環(huán)境準(zhǔn)備SLIST *pPre = pHead; //保存當(dāng)前結(jié)點(diǎn)pCur的前驅(qū)SLIST *pCur = pHead->next;//查找值為y的結(jié)點(diǎn)while(pCur != NULL){if(pCur->data == y){break;}pPre = pCur;pCur = pCur->next;} //while循環(huán)后,有兩種情況:查找到值為y的結(jié)點(diǎn);沒(méi)查找到值為y的結(jié)點(diǎn)//1.如果沒(méi)有找到值為y的結(jié)點(diǎn)if(pCur == NULL) {return -1; }else //2.如果找到值為y的結(jié)點(diǎn):此時(shí)pCur指向值為y的結(jié)點(diǎn),pPre指向值為y的結(jié)點(diǎn)的前驅(qū){//刪除y結(jié)點(diǎn)pPre->next = pCur->next;free(pCur);pCur = NULL;return 0;} } //銷毀鏈表 int SList_Destroy(SLIST* pHead) {SLIST *pTmp = NULL; //當(dāng)前結(jié)點(diǎn)的后繼SLIST *pCur = pHead; //當(dāng)前結(jié)點(diǎn)if(pHead == NULL) //如果是空鏈表return -1;while(pCur){pTmp = pCur->next; free(pCur);pCur = pTmp;}return 0; }int SList_Reverse(SLIST* pHead) //鏈表的逆置,注意:使當(dāng)前指針pCur指向第二個(gè)結(jié)點(diǎn) { if(NULL==pHead) //如果傳入的頭結(jié)點(diǎn)為空,則error{return -1; //異常返回}//如果不夠兩個(gè)業(yè)務(wù)結(jié)點(diǎn),則不用逆置鏈表,直接返回 //即:只有頭結(jié)點(diǎn)沒(méi)有業(yè)務(wù)結(jié)點(diǎn)||只有一個(gè)業(yè)務(wù)結(jié)點(diǎn)if( (NULL==pHead->next)||(NULL == pHead->next->next) ) return 0; //不用逆置,直接返回 //-------------------------------------------------------------- //如果至少有兩個(gè)業(yè)務(wù)結(jié)點(diǎn),則需要逆置鏈表//環(huán)境準(zhǔn)備SLIST *pCur = pHead->next->next; //當(dāng)前結(jié)點(diǎn)直接從第二個(gè)業(yè)務(wù)結(jié)點(diǎn)開始SLIST *pPre = pHead->next; //用于保存當(dāng)前結(jié)點(diǎn)的前驅(qū),每次都把pPre與pCur進(jìn)行交換SLIST *pTmp = NULL; //輔助指針(用來(lái)提前保存指向當(dāng)前結(jié)點(diǎn)的后繼的指針,緩存指針位置)while(pCur != NULL){//逆置前,先保存(“緩存”)當(dāng)前結(jié)點(diǎn)的后繼(防止斷鏈)pTmp = pCur->next; //逆置過(guò)程:使當(dāng)前結(jié)點(diǎn)pCur指向它的前驅(qū)結(jié)點(diǎn)pPrepCur->next = pPre;//逆置后,讓pPre、pCur后移一個(gè)位置(重置準(zhǔn)備環(huán)境)pPre = pCur;pCur = pTmp;} //while完成后,還剩下頭結(jié)點(diǎn)和第一個(gè)結(jié)點(diǎn)的指針域沒(méi)有處理,下面進(jìn)行處理pHead->next->next = NULL; //【重點(diǎn)】設(shè)置原本的第一個(gè)業(yè)務(wù)結(jié)點(diǎn)的指針域?yàn)镹ULLpHead->next = pPre; //把頭結(jié)點(diǎn)指向原鏈表的尾結(jié)點(diǎn)return 0;//總結(jié):用到3個(gè)結(jié)構(gòu)體變量,pPre、pCur、pTmp//其中:pPre、pCur用于每次逆置; pTmp用于在逆置前保存pCur的后繼(防止斷鏈)//逆置完成后pPre指向原鏈表的最后一個(gè)結(jié)點(diǎn)//【重要】逆置全部完成后,不要忘記兩件事://1.把pHead->next = pPre;(把頭結(jié)點(diǎn)的指針域指向最后一個(gè)結(jié)點(diǎn))//2.把新鏈表的尾結(jié)點(diǎn)(即:原鏈表的第一個(gè)結(jié)點(diǎn),為pHead->next)設(shè)置為NULL,即pHead->next->next = NULL; } /* 鏈表操作的技巧:1.明確 pHead、pPre、pCur、pNext、pTail、pTmp的位置1.初始化上面的幾個(gè)變量:即環(huán)境準(zhǔn)備while(...) //一般情況下是 while(pCur != NULL){2.處理上面的幾個(gè)變量3.重置上面幾個(gè)變量的位置:即重置環(huán)境}4.退出while時(shí),要“明確一共分為幾個(gè)情況”以及在每種情況下,上面幾個(gè)變量的位置。5.進(jìn)行最后的操作 */

鏈表逆置的解析圖

總結(jié)

以上是生活随笔為你收集整理的第六天2017/04/11(1:结构体链表基础和相关经典操作)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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