【轉+】線性表(順序表和單鏈表)

轉自大神 權侵刪    https://www.cnblogs.com/lichuankai/p/8627665.htmlhtml

1、定義:是n個類型相同的數據元素的有限序列。數組

  線性表元素的個數n(n>=0)定義爲線性表的長度,當n=0時,稱爲空表。函數

  在較複雜的線性表中,一個數據元素能夠由若干個數據項組成。性能

3、線性表的順序存儲結構spa

  一、順序存儲定義:線性表的順序存儲結構,指的是用一段地址連續的存儲單元依次存儲線性表的數據元素。指針

  二、順序存儲方式code

  描述順序存儲結構須要三個屬性:htm

    a、存儲空間的起始位置:數組data,它的存儲位置就是存儲空間的存儲位置。blog

    b、線性表的最大存儲容量:數組長度MaxSize.element

    c、線性表的當前長度:length。

#define MAXSIZE  100 typedef struct{ ElementType element[MAXSIZE];//線性表佔用的數組空間
      int last;//記錄線性表中最後一個元素的下標值,空表置爲-1

}List;//別忘分號
一個這個 就是表示的一個線性表(以數組的形式順序存儲)了 想用的話就跟數組沒啥區別

(last表示的是下標值,因此表示順序表中序號爲i的元素: l->elem[i-1]   順序表的長度:l->last+1; )

 

  三、數據長度與線性表長度的區別

    a、數組長度:數組的長度是存放線性表的存儲空間的長度存儲分配後這個量是通常是不變的。

    b、線性表長度:線性表長度是線性表中數據元素的個數,隨着線性表插入和刪除操做的進行,這個量是變化的。

  在任意時刻,線性表的長度應該小於等於數組的長度。

  四、地址計算方法

  存儲器中的每一個存儲單元都有本身的編號,這個編號稱爲地址。

  假設佔用的是c個存儲單元,那麼線性表中第i+1個數據元素的存儲位置和第i個數據元素的存儲關係知足下列關係(LOC表示得到存儲位置的函數)。

  因此對於第i個數據元素a1的存儲位置能夠由a1推算得出:

    

4、順序存儲結構的初始化 插入 刪除 查找

【都是不帶頭結點的 】滾麻痹數組要個鬼的頭結點

初始化:

List MakeEmpty(){ List p; p=(List)malloc(sizeof(List)); p->last=-1; return p;//不用指針也闊以的
}

 

查找:

1>按序號查找:直接L->element[i-1]啊;

2>按內容查找

int SearchPosition(List L,ElementType e){ int i=0; while(i<=L->last&&L->element[i]!=e){ i++; } if(i<=L->last){ return i+1;//返回其在序列的序號 最好別省事返回個在數組的下標哈
 } else{ return -1; } }

 

插入:

#define true 1;
#define error 0;
int
Insert(List *L,int i, ElementType e){ //在i以前插入 int k; if(L->last>L->elem[MAXSIZE]-1){ printf("表滿沒法插入");
return (false); }
else{ if(i<0||i>L->last+1){ printf("插入位置不對");
return (false); }
else{ for(k=L->last;k>=i;k--){ L->elem[k+1]=L->elem[k]; } L->elem[i-1]=e; L->last++;//!! }
return (true); } }
//元素平均移動次數:n/2 【在表頭插入 移動n個數據 表尾插入 一個不動】

 

刪除:

int Delete(List L,int i,Element *p){//刪除第i個元素
      int k; if(L->last==-1){ printf("空表"); return (false); } else{ if(i<1||i>L->last+1){ printf("元素位置不對"); return (false); } else{ *p=L->element[i-1]; for(k=i-1;k<L->last;k++){ L->element[k]=L->element[k+1]; } L->last--; return (true); } } }
//平均移動次數 n-1/2 【刪除表尾不須要移動元素 刪除表頭移動n-1次】

 

  四、線性表順序存儲結構的優缺點

    優勢:

      a、無須爲表示表中元素之間的邏輯關係而增長額外的存儲空間。

      b、能夠快速地存取表中任一位置的元素。

    缺點:

      a、插入和刪除操做須要移動大量元素。

      b、當線性表長度變化較大時,難以肯定存儲空間的容量。

      c、形成存儲空間的「碎片」。

 

5、線性表的鏈式存儲結構(動態存儲方式)( 就是 單鏈表)

  一、線性錶鏈式存儲結構定義

    爲了表示每一個數據元素a與其直接後繼數據元素之間的邏輯關係,對數據元素a來講,除了存儲其自己的信息以外,還需存儲一個指示其後繼的信息(即直接後繼的存儲位置)。咱們把存儲數據元素信息的域稱爲數據域,把存儲直接後繼位置的域稱爲指針域。指針域中存儲的信息稱做指針或鏈。這兩部分信息組成數據元素a的存儲映像,稱爲結點。

n個結點(a的存儲映像)鏈結成一個鏈表,即爲線性表的鏈式存儲結構,由於此鏈表的每一個結點中只包含一個指針域,因此叫作單鏈表

 把鏈表中的第一個結點的存儲位置叫作頭指針。規定,線性鏈表的最後一個結點指針爲「空」。 習慣上用頭指針代替單鏈表

有時,爲了方便對鏈表進行操做,會在單鏈表的第一個結點前附設一個結點,稱爲頭結點。頭結點的數據域能夠不存儲任何信息。

  

  二、頭指針與頭結點的異同

  頭指針:

    a、頭指針是指鏈表指向第一個結點的指針,若鏈表有頭結點,則是指向頭結點的指針。

    b、頭指針具備標識做用,因此經常使用頭指針冠以鏈表的名字。

    c、不管鏈表是否爲空,頭指針均不爲空。頭指針是鏈表的必要元素。

  頭結點:

    a、頭結點是爲了操做的統一和方便而設立的,放在第一元素的結點以前,其數據域通常無心義(也可存放鏈表的長度)。

    b、有了頭結點,對在第一元素結點前插入結點和刪除第一結點,其操做與其餘結點的操做就同一了。

    c、頭結點不必定是鏈表必須元素

單鏈表的存儲結構:

typedef struct Node{ ElementType data; struct Node *next; }Node, *ListNode;

//這個表示的是一整個單鏈表中的一個元素 由一堆這個構成一個單鏈表

 

初始化單鏈表:

ListNode InitList (ListNode L){ L=(ListNode)malloc(sizeof(Node)); L->next=NULL;//帶頭結點
       L=NULL;//不帶頭結點
       return L; //L是單鏈表的頭指針,它指向表中的第一個節點(對於帶頭結點的單鏈表,則指向單鏈表的頭結點)(頭指針是必定有的 頭結點不必定)
}

 

建立單鏈表://這是用鏈表示線性表  而不是數組  typedef那只是一個鏈表元素

1>頭插法:

帶頭結點 不帶頭結點

2>尾插法:帶頭結點 不帶頭結點

 

查找

1>按序號

ListNode Get(ListNode L,int i){//查找第i個節點

      int j=0; ListNode p; p=L; if(i<=0) return NULL; while(p->next!=NULL&&j<i){//下標是i-1
         p=p->next; j++; } if(i==j){ return p;} else{ return NULL; } }時間複雜度爲O(n)

 

2>按值查找:

ListNode Get(ListNode L,ElementType e){//查找
 ListNode p; p=L->next; while(p!=NULL){ if(p->data==e){ return p; } else{ p=p->next; } } }//時間複雜度爲O(n)

 

求單鏈表的長度:

int Length(ListNode L){ int i=0; ListNode p; p=L->next; while(p!=NULL){ i++; p=p->next; } return i; }
//時間複雜度爲O(n)
 

 

單鏈表的插入:(頭結點)

 

void Insert(ListNode L,int i,ElementType e){//在第i個元素以前插入節點
 ListNode p,q; p=L; int k=0; while(p!=NULL&&k<i-1){ p=p->next; k++; } if(p==NULL){ printf("數據錯誤超出")}; q=(ListNode)malloc(sizeof(Node)); q->data=e; q->next=p->next; p->next=q; // return L;
 }

 

刪除第i個元素:

void Delete(ListNode L,int i,ElementType *e){//將線性表第i個元素刪除 並付給e
 ListNode p,q,temp; int k=0; p=L; while(p!=NULL&&k<i){ p=p->next; k++; } if(p==NULL){ printf("位置不合理"); } temp=p->next; p->next=temp->next; *e=temp->data;//加不加*就是值傳遞和引用傳遞的區別
         
          free(temp);//由於建立鏈表各個元素的時候是用malloc來的 因此不用時要清除掉空間
 }

 

刪除整個表:

void Delete(ListNode L){ ListNode p,temp; p=L->next; while(p->next!=NULL){ temp=p; p=p->next; free(temp); } L->next=NULL; }

 

 

8、單鏈表結構與順序存儲結構優缺點

  一、單鏈表結構和順序存儲結構對比:

    a、存儲分配方式:

    順序存儲結構用一段連續的存儲單元依次存儲線性表的數據元素。

    單鏈表採用鏈式存儲結構,用一組任意的存儲結構單元存放線性表的元素。

    b、時間性能:

    查找:順序存儲結構O(1),單鏈表O(n)。

    插入和刪除:順序存儲結構須要平均移動表長一半的元素,時間爲O(n)。單鏈表在線出某位置的指針後,插入和刪除時間僅爲O(1)。

c、空間性能:順序存儲結構須要預分配存儲空間,分大了,浪費,分小了易發生上溢。單鏈表不須要分配存儲空間,只要有就能夠分配,元素個數也不受限制。

相關文章
相關標籤/搜索