国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

頭疼的算法與數據結構——單鏈表詳解

2019-11-06 06:39:42
字體:
來源:轉載
供稿:網友

一、鏈表簡介

1.基本信息

鏈表是一種常見的數據結構,不同于數組,在內存中是連續的一段內存空間,,雖然是一種線性表但是不會按照線性順序去存儲數據的數據結構,而是在每一個節點里存到下一個節點的指針(Pointer)。由于不必按順序存儲,鏈表在插入的時候可以達到O⑴的復雜度,比另一種線性表:順序表快得多,但是查找一個節點或者訪問特定編號的節點則需要O(n)的時間,而順序表相應的時間復雜度分別是O(logn)和O⑴。使用鏈表結構可以克服數組鏈表需要預先知道數據大小的缺點,鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理。但是鏈表失去了數組隨機讀取的優點,同時鏈表由于增加了結點的指針域,空間開銷比較大。在計算機科學中,鏈表作為一種基礎的數據結構可以用來生成其它類型的數據結構。鏈表通常由一連串節點組成,每個節點包含任意的實例數據(data fields)和一或兩個用來指向上一個/或下一個節點的位置的鏈接(links)。鏈表最明顯的好處就是,常規數組排列關聯項目的方式可能不同于這些數據項目在記憶體或磁盤上順序,數據的存取往往要在不同的排列順序中轉換。而鏈表是一種自我指示數據類型,因為它包含指向另一個相同類型的數據的指針(鏈接)。鏈表允許插入和移除表上任意位置上的節點,但是不允許隨機存取。鏈表有很多種不同的類型:單向鏈#表,雙向鏈表以及循環鏈表。鏈表可以在多種編程語言中實現。像Lisp和Scheme這樣的語言的內建數據類型中就包含了鏈表的存取和操作。程序語言或面向對象語言,如C,C  和java依靠易變工具來生成鏈表。

2.特點

數組的缺點在鏈表上就是優點,鏈表的確定就是數組的優點,合理利用這兩種數據結構會讓你的程序變得簡單。線性表的鏈式存儲表示的特點是用一組任意的存儲單元存儲線性表的數據元素(這組存儲單元可以是連續的,也可以是不連續的)。因此,為了表示每個數據元素 與其直接后繼數據元素 之間的邏輯關系,對數據元素 來說,除了存儲其本身的信息之外,還需存儲一個指示其直接后繼的信息(即直接后繼的存儲位置)。由這兩部分信息組成一個結點(如概述旁的圖所示),表示線性表中一個數據元素。線性表的鏈式存儲表示,有一個缺點就是要找一個數,必須要從頭開始找起,十分麻煩。  

二、鏈表圖解(linked List)

下圖就是最簡單最一般的單向鏈表:還有這種:多一個Tail指針,好處就是能很方便地找到末尾。留一個終始標志,這個節點作為一個標志,不用于存儲數據,鏈表末尾指向這個節點,形成一個“環形鏈表”,這樣無論在鏈表的哪里插入新的元素,操作都一致了,不必判斷頭和尾的特殊性。數組的好處就是鏈表的壞處,數組的壞處就是鏈表的好處,鏈表插入刪除方便,遍歷麻煩;數組遍歷方便,插入刪除都要移動。因為需要從頭開始找,沒辦法像數組那樣直接跳到那個地址。而插入元素,就比數組方便了,如果你已經得知了要插入的地址的話,不過還要注意哦,是“后插入”(Insert After):有“后插入”,那就有“前插入”(Insert Before),兩者對單向鏈表來說真的不一樣,下圖描述了“前插入”:由于指針向后不向前,我們不知道要插入位置的前一個節點是什么,只能從頭找,所以比較麻煩。

三、單鏈表的基本操作

    今天先實現單鏈表的功能:
#include <stdio.h>struct node{    int data;    struct node *next;};typedef struct node Node;#define SIZE sizeof(Node)//創建節點Node* creteNode(int d){    Node* pn=malloc(SIZE);    pn->data=d;    pn->next=NULL;    return pn;}//創建鏈表void creatList(Node** h){    Node* pn=NULL;    Node* p=NULL;    int d;    PRintf("請輸入數據/n");    scanf("%d",&d);    pn=creteNode(d);    *h=pn;    p=*h;    while(1)    {        printf("請輸入數據/n");        scanf("%d",&d);        if(d==0)            break;        pn=creteNode(d);        p->next=pn;        p=p->next;    }}這就是上面函數創建的createNode函數創建一個個的節點,createList將一個個節點串起來。

//查找某個節點的位置Node* findNode(Node* h,int n){    int i;    if((h==NULL)||(n<0))    {            printf("查找位置不合法||鏈表為空!/n");            return NULL;    }    if(n==1)    {        return h;    }    for(i=1;i<=n;i++)    {        h=h->next;        if(h==NULL)         break;    }    return h;}findNode函數是為了查找某個節點,在插入和刪除時使用這個函數方便。

//末尾增加一個新的節點int addBack(int d,Node* h){    Node *pn=NULL;    pn=creteNode(d);    Node* p=h;    while(p->next)    {        p=p->next;    }    p->next=pn;    pn->next=NULL;}在末尾插入一個節點,先要遍歷到最后一個節點,然后將新節點放在后面。

//頭插法int addFont(int d,Node** h)//修改頭節點  傳入二級指針{    Node* pn=NULL;    pn=creteNode(d);    pn->next=*h;    *h=pn;}同尾插法一樣,在頭節點位置插入一個元素。只是不需要遍歷。

//插入int insertNode(int n,int d,Node** h)//在n位置插入d{    if((n<1)||(*h==NULL))    {        printf("插入位置不合法||鏈表為空!/n");        return 0;    }    Node* pn=creteNode(d);//創建新的節點    //插入位置為1,即插入頭節點的位置    if(n==1)    {        Node* pn=NULL;        pn=creteNode(d);        pn->next=*h;        *h=pn;       return 0;    }    else    {       Node* pf=findNode(h,n-1); //得到插入位置的前一個節點       pn->next=pf->next;       pf->next=pn;       return 1;    }}首先我們用findNode函數找到插入位置的前一個節點,插入的時候要記得先要斷開以前的連接,刪除也是的,先要斷開連接再進行操作。

//刪除第n個位置的元素int deleteNode(int n,Node** h){    //判斷頭節點是否為空,位置是不是合法    if((*h==NULL)||(n<1))    {        printf("刪除的鏈表為空||刪除的位置不合法!/n");        return 0;    }    Node* pd=NULL;    //判斷是否只有一個頭節點    if(((*h)->next)==NULL)    {        printf("只用一個節點/n");        return 0;    }    //刪除頭節點    if(n==1)    {        pd=*h;        *h=pd->next;        free(pd);        pd=NULL;        return 1;    }    //刪除    //判斷節點是否存在    if(NULL==findNode(*h,n-1))    {        printf("刪除節點不存在/n");        return 0;    }    //找到要刪除的節點的前一個節點    Node* pf=findNode(*h,n-1);    pd=pf->next;//將要刪除的節點的給pd    pf->next=pd->next;    free(pd);    pd=NULL;    pf=NULL;    return 1;}

也是用findNode函數找到前一個節點的位置,然后先斷開刪除節點位置和后面一個節點的位置。

//打印鏈表void print(Node* h){    printf("list:/n");    while(h)    {        printf("%d ",h->data);        h=h->next;    }    printf("/n");}int main(){    Node* head=NULL;    creatList(&head);    print(head);    Node* p=findNode(head,0);    printf("%d/n",p->data);    deleteNode(2,&head);    print(head);    return 0;}


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 增城市| 怀化市| 荃湾区| 托克托县| 新兴县| 寿阳县| 华池县| 鄂温| 嵊州市| 东至县| 玛沁县| 旅游| 石泉县| 泊头市| 孙吴县| 宁强县| 临夏市| 新郑市| 晋江市| 元江| 荔浦县| 江阴市| 双流县| 襄城县| 永嘉县| 鹤壁市| 根河市| 中方县| 西峡县| 四川省| 兴安县| 南昌市| 六安市| 曲周县| 唐海县| 西平县| 礼泉县| 呼和浩特市| 大安市| 家居| 伊川县|