資料結構整理——線性連結串列
阿新 • • 發佈:2018-12-16
#線性表的鏈式表示和實現
##1.線性表的鏈式表示
總共有三種方式
1.線性連結串列
2.雙向連結串列
3.迴圈連結串列
###1.1不同實現形式的優點
####一、線性連結串列
就是相當普通的連結串列,就不做過多的介紹。相較於陣列,其儲存不強調連續性,其儲存的物理位置不要求緊鄰。(因此不可以用上一個節點+1來表示下一節點 曾經看了好久的一個bug)有一個小技巧是你可以將這個連結串列的表頭置為空,在在頭節點之前加入元素的時候會異常方便(誰用誰知道)
####二、雙向連結串列
在檢查每一個節點的前驅的時候如果我們按照普通的連結串列形式的話,只能從頭開始去找,有時候會顯得異常繁瑣,所以這個時候就出現了雙向連結串列,在節點的結構體中加入一個指標指向上一個節點。
####三、迴圈連結串列
連結串列中最後一個節點的指標指向頭節點,整個節點會形成一個環。在處理某些問題時會非常好用 (沒錯就是 約瑟夫環問題)
##2.最簡單的實現形式的程式碼
#include <stdio.h> #include "init.h" #include <stdlib.h> typedef int ElemType; typedef struct Node { ElemType data; struct Node* next; }Node,*pNode; typedef struct { pNode head,tail; int length; }LinkList; pNode GetHead(LinkList L) { return L.head; }//獲得連結串列頭節點的置為 pNode GetLast(LinkList L) { return L.tail; }//獲得尾節點 pNode PriorPos(LinkList L,pNode p) { pNode q=L.head; while(q->next!=p) { q=q->next; } return q; }//求某個節點前驅的位置 pNode NextPos(LinkList L,pNode p) { return p->next; }//下一個位置 Status LocatePos(LinkList L,int i,pNode &p) { int count=0; pNode q=L.head; while(count<i) { q=q->next; count++; } p=q; return OK; }//定位第i個節點的位置 pNode LocateElem(LinkList L,ElemType e) { pNode p=L.head; while(p) { if(p->data==e) { return p; } p=p->next; } return ERROR; }//獲得第i個節點的位置 Status MakeNode(pNode &p,ElemType e) { p=(pNode)malloc(sizeof(ElemType)); if(!p) return ERROR; p->data=e; return OK; }//初始化一個新的節點 void FreeNode(pNode &p) { free(p); p=NULL; }//釋放節點 Status InitList(LinkList &L) { L.length=0; L.head=(pNode)malloc(sizeof(ElemType)); L.head=NULL; L.tail=(pNode)malloc(sizeof(ElemType)); L.tail->next=NULL; return OK; }//初始化佇列 Status DestoryList(LinkList &L) { if(L.head==NULL) return ERROR; pNode p=L.head; pNode q; while(p) { q=p; p=p->next; FreeNode(q); } L.length=0; return OK; }//摧毀一個雷諾 Status ClearList(LinkList &L) { if(L.head==NULL) return ERROR; pNode p=L.head->next; pNode q; while(p) { q=p; p=p->next; FreeNode(q); } L.length=0; L.head->next=NULL; return OK; }//清除佇列 Status InsFirst(pNode h,pNode s) { s->next=h->next; h->next=s; return OK; }//在結點之前插入 Status DelFirst(pNode h,pNode &q) { q=h->next; h->next=h->next->next;//這裡我們也可以看出連結串列的方便之處 return OK; }//刪除節點 Status Append(LinkList &L,pNode s) { L.tail->next=s; int count=0; while(s->next!=NULL) { s=s->next; count++; } L.tail=s; L.tail->next=NULL; L.length+=count; return OK; }//連結連結串列跟節點s Status Remove(LinkList &L,pNode &q) { pNode p; p=L.head; q=L.tail; while(p->next!=L.tail) { p=p->next; } FreeNode(L.tail); L.tail=p; p->next=NULL; L.length--; return OK; } Status InsBefore(LinkList &L,pNode &p,pNode s) { pNode q=PriorPos(L,p); q->next=s; p->next=s->next; s->next=p; L.length++; return OK; }//節點之前插入 Status InsAfter(LinkList &L,pNode &p,pNode s) { s->next=p->next; p->next=s; L.length++; return OK; }//節點之後插入 Status SetCurElem(pNode &p,ElemType e) { p->data=e; return OK; }//更改節點中每某個節點的值 Status Elem(pNode q) { return q->data; }//得到該節點的值 Status ListEmpty(LinkList L) { if(L.length==0) { return true; } return false; }//判空 int ListLength(LinkList L) { return L.length; }//獲得長度 Status ListTraverse(LinkList L) { pNode p=L.head; while(p) { printf("%d\n",p->data); p=p->next; } return OK; }//遍歷連結串列 Status CreatList(LinkList &L) { printf("please input the number of node:"); int n; scanf("%d",&n); L.length+=n; pNode p,q; p=q=(pNode)malloc(sizeof(Node)); int number; for(int i=1;i<=n;i++) { scanf("%d",&number); p->data=number; if(i==1) { L.head=p; } q=p; p=(pNode)malloc(sizeof(Node)); q->next=p; } q->next=NULL; L.tail=q; }//建立連結串列 int main() { LinkList L; InitList(L); CreatList(L); printf("%d\n",ListEmpty(L)); ListTraverse(L); pNode p,q; MakeNode(q,3); MakeNode(p,4); InsAfter(L,p,q); InsBefore(L,p,q); ListTraverse(L); printf("%d\n",ListLength(L)); SetCurElem(L.head,5); ListTraverse(L); return 0; }
略懶只實現了第一種最簡單的,日後有空再補上其他的吧