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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

三、链表(实践)

發布時間:2025/3/19 编程问答 11 豆豆
生活随笔 收集整理的這篇文章主要介紹了 三、链表(实践) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

絮絮叨叨

如何輕松寫鏈表的代碼?

  • 有決心并付出精力
  • 理解指針或引用的含義
    • 將某個變量賦值給指針,實際上就是將這個變量的地址賦值給指針,或者反過來說,指針中存儲了這個變量的內存地址,指向了這個變量,通過指針就能找到這個變量。
  • 警惕指針丟失和內存泄漏
  • 利用哨兵(頭結點)簡化實現難度
  • 重點留意邊界條件處理
    • 如果鏈表為空時,代碼是否能正常工作?
    • 如果鏈表只包含一個結點時,代碼是否能正常工作?
    • 如果鏈表只包含兩個結點時,代碼是否能正常工作?
    • 代碼邏輯在處理頭結點和尾結點的時候,是否能正常工作?
  • 舉例畫圖,輔助思考

一、數據結構

1、單向鏈表

  • 結點包括:數據域 + 指針域
    • 數據域:存儲數據元素的值
    • 指針域(鏈域):存儲下一個結點地址或者指向其后繼結點的指針
// 定義結點 Node typedef struct Node{ElemType data;struct Node * next; } Node; // 定義指向結點 Node 類型對象的指針 LinkList typedef struct Node *LinkList;

2、雙向鏈表

  • 結點包括:數據域 + 左指針域(prev) + 右指針域(next)
struct DNode{int data;DNode * prev;DNode * next; }

二、基本操作實例

1、單鏈表的讀取

(1)獲取鏈表第 i 個數據結點的算法思路:

  • 聲明一個指針 p 指向鏈表的第一個結點,初始化 j 從 1 開始;
  • 當 j < i 時,遍歷鏈表,p 不斷指向下一個結點, j++;
  • 若到鏈表末尾 p 為空, 則說明第 i 個元素不存在;
  • 否則查找成功,返回結點 p 的數據。

(2)實現

由于單鏈表的結構中沒有定義表長,所以不能事先知道要循環多少次,因此不方便用for循環來控制循環。==》while循環

# define OK 1 # define ERROR 0 # define TRUE 1 # define FALSE 0 typdef int Status; //Status是函數的類型,其值為函數結果狀態碼,eg:OK等 /*初始條件:順序線性表L已存在,1≤i≤ListLength(L)*/ /*操作結果: 用e返回L中第i個數據元素的值*/ Status GetElem( Node *L, int i, Elemtype *e){ int j;LinkList p; // 聲明指針pp = L->next; //讓p指向鏈表L的第一個節點j = 1;while(p && j<i) //當p不為空 或 j 小于i時,繼續循環{p = p->next;++j;}if(!p || j>i )return ERROR;*e = p->data;return OK; }

2、插入結點(單向鏈表)

s->next = p->next;
p->next = s

(1)第 i 個數據插入結點的算法思路:

  • 聲明一個指針p指向鏈表的第一個結點,初始化j=1;
  • 當 j < i 時,遍歷鏈表,讓指針 p 向后移動,不斷指向下一結點,++j;
  • 若到鏈表末尾 p 為空,說明第 i 個元素不存在;
  • 否則查找成功,在系統中生成一個空結點 s;
  • 將數據元素 e 賦值給 s->data;
  • 單鏈表的插入標準語句:s->next = p->next; p->next = s
  • 返回成功

(2)實現

/*初始條件:順序線性表L已存在,1≤i≤ListLength(L)*/ /*操作結果:在L中第i個位置之前插入新的數據元素e,L的長度加1*/ Status ListInsert(LinkList *L, int i, ElemType e) {int j;LinkList p,s;p = *L;j = 1;while(p && j<i) //尋找第i個結點{p = p->next;++j;}if(!p || j>i ) // 第i個結點不存在return ERROR;s = (LinkList)malloc(sizeof(Node)); //生成新的結點s->data = e;s->next = p->next; //將p的后繼結點賦值給s的后繼p->next = s; //將s賦值給p的后繼return OK; }

3、刪除結點(單向鏈表)

p->next = p->next->next
用q取代p->next的話,上面等價于:

q = p->next; p->next=q->next

(1)第 i 個數據刪除結點的算法思路:

  • 聲明一個指針p指向鏈表的第一個結點,初始化 j 從1開始;
  • 當 j<i 時,遍歷鏈表,讓指針p向后移動,不斷,指向下一結點,++j;
  • 若到鏈表末尾p為空,說明第i個結點不存在;
  • 否則查找成功,將欲刪除的結點p->next賦值給q;
  • 單鏈表的刪除標準語句:p->next = q->next;
  • 將q結點中的數據賦值給e,作為函數的返回值
  • 釋放q結點
  • 返回成功

(2)實現

#include<stdio.h>Status ListDelete(LinkList *L, int i, ElemType *e) {int j;LinkList p,q;p = *L;j = 1;while(p->next && j<i){ //遍歷查找第i個結點p = p->next;++j;}if(!(p->next) || j>i)return ERROR;q = p->next;p->next = q->next;*e = q->data;free(q);return OK; }

4、單鏈表的整表創建

單鏈表的整表創建過程就是一個動態生成鏈表的過程。由“空表”的初始狀態,依次建立各元素結點,并逐個插入鏈表。

(1)算法思路(頭插法):

  • 聲明一結點 p 和 計數器變量 i;
  • 初始化一空鏈表 L;
  • 讓 L 的頭結點的指針指向NULL,即建立一個帶頭結點的單鏈表;
  • 循環:
    • 生成一個新結點賦值給 p;
    • 隨機生成一個數組賦值給 p 的數據域 p->data;
    • 將 p 插入到頭結點與前一新結點之間。

(2)實現

頭插法

/* 隨機產生n個元素的值,建立帶頭結點的單鏈表L */ void CreateListHead(LinkList *L, int n) { LinkList p;int i;srand(time(0)); //初始化隨機種子*L = (LinkList)malloc(sizeof(Node));(*L)->next = NULL; //建立一個帶頭結點的單鏈表for(i = 0; i < n; i++){p = (LinkList)malloc(sizeof(Node)); //生成新結點p->data = rand()%100 + 1;p->next = (*L)->next;(*L)->next = p;} }

尾插法

/* 隨機產生n個元素的值,建立帶頭結點的單鏈表L */ void CreateListHead(LinkList *L, int n) { LinkList p, r;int i;srand(time(0)); //初始化隨機種子*L = (LinkList)malloc(sizeof(Node));r = *L; // *r 指向尾部的結點for(i = 0; i < n; i++){p = (LinkList)malloc(sizeof(Node)); //生成新結點p->data = rand()%100 + 1;r->next = p;r = p;}r->next=NULL; }

5、單鏈表的整表刪除

(1)算法思路

  • 聲明結點結點 p 和 q;
  • 將第一個結點賦值給 p;
  • 循環:
    • 將下一結點賦值給 q;
    • 釋放 p;
    • 將 q 賦值給 p;

(2)實現

/*初始條件:順序線性表L已存在,操作結果:將L充值為空表*/ Status CLearList(LinkList *L) { LinkList p,q;p = (*L)->next;while(p){q = p->next;free(p);p = q;}(*L)->next = NULL;return OK; }

三、常見操作

1、單鏈表反轉

法一:反向遍歷鏈表就類似于事先遍歷的節點后輸出,即“先進后出”,那么可以將鏈表遍歷存放于棧中,其后遍歷棧依次彈出棧節點,達到反向遍歷效果。

//1.stack void printLinkedListReversinglyByStack(Node *head){stack<Node* > nodesStack;Node* pNode = head;//遍歷鏈表while (pNode != NULL) {nodesStack.push(pNode);pNode = pNode->next;}while (!nodesStack.empty()) {pNode=nodesStack.top();printf("%d\t", pNode->value);nodesStack.pop();} } //2.遞歸 void printLinkedListReversinglyRecursively(Node *head){if (head!=NULL) {if (head->next!=NULL) {printLinkedListReversinglyRecursively(head->next);}printf("%d\t", head->value);} }

2、鏈表中環的檢查,獲取連接點,計算環的長度

判斷鏈表是否有環路,獲取連接點,計算環的長度
此題很有意思,具體詳細請參考:http://www.cnblogs.com/xudong-bupt/p/3667729.html

判斷是否含有環:slow和fast,slow指針每次走一步,fast指針每次走兩步,若是鏈表有環,fast必能追上slow(相撞),若fast走到NULL,則不含有環。

//判斷是否含有環 bool containLoop(Node* head){if (head==NULL) {return false;}Node* slow = head;Node* fast = head;while (slow!=fast&&fast->next!=NULL) {slow = slow->next;fast = fast->next->next;}if (fast==NULL) {return false;}return true; }

判斷環的長度:在相撞點處,slow和fast繼續走,當再次相撞時,slow走了length步,fast走了2*length步,length即為環得長度。

//獲得環的長度 int getLoopLength(Node* head){if (head==NULL) {return 0;}Node* slow = head;Node* fast = head;while (slow!=fast&&fast->next!=NULL) {slow = slow->next;fast = fast->next->next;}if (fast==NULL) {return 0;}//slow和fast首次相遇后,slow和fast繼續走//再次相遇時,即slow走了一圈,fast走了兩圈int length = 0;while (slow!=fast) {length++;slow = slow->next;fast = fast->next->next;}return length; }

環得連接點:slow和fast第一次碰撞點到環的連接點的距離=頭指針到環的連接點的距離,此式可以證明,詳見上面鏈接。

//獲得環的連接點 Node* getJoinpoit(Node* head){if (head==NULL) {return NULL;}Node* slow = head;Node* fast = head;while (slow!=fast&&fast->next!=NULL) {slow = slow->next;fast = fast->next->next;}if (fast==NULL) {return NULL;}Node* fromhead = head;Node* fromcrashpoint = slow;while (fromcrashpoint!=fromhead) {fromhead = fromhead->next;fromcrashpoint = fromcrashpoint->next;}return fromhead; }

3、找出中間節點

用slow和fast指針標記,slow每次走一步,fast每次走兩步,當fast到尾節點時,slow就相當于總長度的一半,即在中間節點。

//找出中間節點 Node* findMidNode(Node* head){Node* slow = head;Node* fast = head;while (fast->next != 0&&fast->next->next!=0) {slow = slow->next;fast = fast->next->next;}return slow; }

4、找出倒數第k個節點

用slow和fast指針標記,fast指針事先走k步,然后slow和fast同時走,當fast到達末節點時,slow在fast的前k個節點,即為倒數第k個節點。

//找出倒數第k個節點 Node* findKNode(Node* head,int k){Node *temp1 = head;Node *temp2 = head;while (k-->0) {if(temp2 == NULL){return NULL;}temp2 =temp2->next;}while (temp2->next != NULL&&temp2->next->next!=NULL) {temp1 = temp1->next;temp2 = temp2->next->next;}return temp1; }

總結

以上是生活随笔為你收集整理的三、链表(实践)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 亚洲伊人网站 | 欧美激情一区二区三区蜜桃视频 | 亚洲六月丁香色婷婷综合久久 | 日韩精选在线观看 | 日p免费视频 | 国产 欧美 自拍 | 欧美久久久精品 | 国内特级毛片 | 日韩av手机在线免费观看 | 国产乱淫av公| 驯服少爷漫画免费观看下拉式漫画 | 5级黄色片 | 91精品视频在线 | 欧美色图亚洲视频 | 中文字幕有码在线播放 | 亚洲a网| 精品国产av 无码一区二区三区 | 久久久久久久一区二区 | 国产一区二区三区影视 | 亚洲综合婷婷久久 | 欧美日韩综合一区二区 | 五月婷婷中文字幕 | 美女黄色一级视频 | 欧美激情在线一区二区 | 欧美又粗又长 | 三级国产在线 | 日本一区视频在线 | 在线免费日本 | 国产精品人人做人人爽 | 精品人妻一区二区三区四区五区 | 美女视频黄是免费 | 亚洲综合在线中文字幕 | 国产黄色录像片 | 成年人免费看视频 | 亚洲AV乱码国产精品观看麻豆 | 一区二区三区四区国产 | 久操不卡 | 特黄一区| 好吊妞这里有精品 | 伊人久久免费视频 | 欧洲一区二区三区在线 | 精品在线视频免费观看 | 超碰婷婷| 欧美亚洲高清 | 亲女禁h啪啪宫交 | 骚虎视频在线观看 | 少妇3p视频| 偷拍中国夫妇高潮视频 | 亚洲中文字幕在线观看 | 玉女心经在线看 | 人妻熟人中文字幕一区二区 | 欧美性猛交久久久乱大交小说 | 二区三区 | 国产视频不卡 | 国产综合久久久久久鬼色 | 永久免费不卡在线观看黄网站 | 欧美高清性xxxxhdvideosex | 中文字幕在线第一页 | 牛牛电影国产一区二区 | 国产欧美精品区一区二区三区 | 自拍偷拍在线视频 | 国产精品免费看久久久无码 | 又色又爽又黄 | 一区二区三区在线免费播放 | 一区二区视频免费在线观看 | 久久久久久久久久成人 | 中国女人内精69xxxxxx | 农民工hdxxxx性中国 | 玖玖热在线视频 | 午夜黄色剧场 | 男人天堂2021 | 男女偷爱性视频刺激 | 男人的天堂在线观看av | 一级aaaa毛片| 一级黄色片在线看 | 五月久久| 玖玖爱在线观看 | 老司机午夜免费福利 | 亚洲一区欧美二区 | 国产香蕉尹人视频在线 | 国产精品露脸视频 | 欧美经典一区二区三区 | 亚洲AV无码国产精品 | 天天视频亚洲 | 激情小说在线观看 | 天堂网ww | 日本va欧美va精品发布 | 一区二区三区中文字幕 | 亚洲国产aⅴ精品一区二区 日韩黄色在线视频 | 日韩一级片免费在线观看 | 日日狠狠| 2018中文字幕在线观看 | 永久免费看mv网站入口78 | 亚洲制服丝袜av | 草草影院在线播放 | 国产精品xxxxx| 日本阿v视频| 日本一二三区在线视频 | 又黄又刺激的视频 |