線性表的順序存儲--
線性表是最基本、最簡單、也是最常用的一種數據結構。線性表(linear list)是數據結構的一種,一個線性表是n個具有相同特性的數據元素的有限序列。
線性表示什么?借助網上大佬的一個例子
小學生放學都是要按順序排隊的,一個接一個,每個小學生的前后位置是固定的,這樣便於迅速清點。
其實這就是一個線性表,從這件事里我們就可以找到很多關於線性表的特性,如
1、線性表是一個序列,它是有順序的(排隊)
2、第一個元素無前驅,最后一個無后繼,其他每個元素都有一個前驅和后繼(一個接一個)
3、元素是有限的(小學生的個數是有限的)
4、數據類型都相同(都是小學生在排隊)
那么我們如何定義一個節點呢?
/*定義線性表類型*/
typedef struct{
ElemType data[MAXSIZE];
int length;
}sqList;
結構較簡單,一個數組用於存放元素信息 和一個長度用於下面操作
代碼實現的功能包括線性表的初始化,判斷是否為空、清空、增加元素、刪除元素、合並線性表等操作。
#include <stdio.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /*初始化存儲空間*/
/*取別名,便以操作*/
typedef int Status;
typedef int ElemType;
/*定義線性表類型*/
typedef struct{
ElemType data[MAXSIZE];
int length;
}sqList;
/*初始化順序線性表*/
Status InitList(sqList *L){
L->length=0;
return OK;
}
/*初始條件:順序表已存在,操作結果:若L為空,則返回TRUE,否則返回FALSE*/
Status ListEmpty(sqList* L){
if(L->length==0)
return TRUE;
else
return FALSE;
}
/* 初始條件:順序線性表L已存在。操作結果:將L重置為空表 */
Status ClearList(sqList* L){
L->length=0;
return OK;
}
/*初始條件:順序線性表L已存在。操作結果:獲取線性表的長度*/
Status ListLength(sqList* L){
return L->length;
}
/* 初始條件:順序線性表L已存在,1≤i≤ListLength(L) */
/* 操作結果:用e返回L中第i個數據元素的值,注意i是指位置,第1個位置的數組是從0開始 */
Status GetElem(sqList* L,int i, ElemType* e){
if(i<1 || i>L->length)
return ERROR;
else
*e = L->data[i-1];
return OK;
}
/* 初始條件:順序線性表L已存在 */
/* 操作結果:返回L中第1個與e滿足關系的數據元素的位序。 */
/* 若這樣的數據元素不存在,則返回值為0 */
Status LocalElem(sqList* L,ElemType e){
int i;
if(L->length==0)
return ERROR;
for(i=0;i<L->length;i++)
if(e==L->data[i])
break;
if(i>=L->length) //沒有找到相匹配的元素
return 0;
return i+1;
}
/* 初始條件:順序線性表L已存在,1≤i≤ListLength(L), */
/* 操作結果:在L中第i個位置之前插入新的數據元素e,L的長度加1 */
Status ListInsert(sqList* L,int i,ElemType e){
int k;
if(L->length == MAXSIZE) return ERROR;
if(i<1 || i>L->length+1) return ERROR;
for(k=L->length-1;k>=i-1;k--)
L->data[k+1]=L->data[k];
L->length++;
L->data[i-1]=e ;
return OK;
}
/* 初始條件:順序線性表L已存在,1≤i≤ListLength(L) */
/* 操作結果:刪除L的第i個數據元素,並用e返回其值,L的長度減1 */
Status ListDelete(sqList* L,int i,ElemType* e){
int k;
if(i<1 || i>L->length) return ERROR;
else
*e = L->data[i-1];
for(k=L->length-1;k>i;k--)
L->data[k]=L->data[k+1];
L->length--;
return OK;
}
/* 初始條件:順序線性表L已存在 */
/* 操作結果:依次對L的每個數據元素輸出 */
Status ListTraverse(sqList* L){
int i;
for(i=0;i<L->length;i++)
printf("%d ",L->data[i]);
return OK;
}
/*求並集*/
void unioList(sqList* La,sqList* Lb){
int La_len,Lb_len,i;
ElemType e;
La_len = La->length;
Lb_len = Lb->length;
for(i=1;i<=Lb_len;i++){
/*用e來獲取Lb線性表中的值*/
GetElem(Lb,i,&e);
if(!LocalElem(La,e))
ListInsert(La,++La_len,e);
}
}
int main(){
//構造一個有10個數的Lb
sqList Lb;
sqList L;
ElemType e;
int i,j,k;
InitList(&L); //初始化
printf("初始化L后:L.length=%d\n",L.length);
/*插入數據*/
for(j=1;j<=5;j++)
ListInsert(&L,1,j);
printf("在L的表頭依次插入1~5后:L.data=");
ListTraverse(&L); //遍歷輸出
printf("\n");
printf("L.length=%d \n",L.length);
i = ListEmpty(&L); //判斷是否為空
printf("L 是否為空:i=%d(1:是 0:否)\n",i);
i =ClearList(&L); //清空線性表
printf("清空L后:L.length=%d\n",L.length);
i = ListEmpty(&L);//判斷是否為空
printf("L 是否為空:i=%d(1:是 0:否)\n",i);
for(j=1;j<=10;j++) /*插入數據*/
ListInsert(&L,j,j);
printf("在L的表尾依次插入1~10后:L.data=");
ListTraverse(&L);
printf("\n");
printf("L.length=%d\n",L.length);
GetElem(&L,5,&e); //取得5號元素
printf("L中第五個元素=%d\n",e);
for(j=7;j<9;j++){
k=LocalElem(&L,j); //判斷是否存在元素
if(k)
printf("存在%d號元素=%d\n ",j,k);
else
printf("No存在%d號元素\n");
}
k=ListLength(&L);
for(j=k+1;j>=k;j--){
i=ListDelete(&L,j,&e); //刪除第j個元素
if(i == ERROR)
printf("刪除第%d個數據失敗\n",j);
else
printf("刪除第%d個的元素值為:%d\n",j,e);
}
printf("依次輸出L的元素:");
ListTraverse(&L);
j=8;
ListDelete(&L,j,&e); //刪除8號元素
printf("刪除第%d個的元素值為:%d\n",j,e);
printf("依次輸出L的元素:");
ListTraverse(&L);
printf("\n");
/*合並La ,Lb*/
InitList(&Lb);
/*插入數據*/
for(j=10;j<=100;j+=10){
ListInsert(&Lb,1,j);
}
unioList(&L,&Lb); //合並
printf("依次輸出合並了Lb的L的元素:");
ListTraverse(&L);
return 0;
}

注意點:
1、線性表其實可以理解是數組的一種特殊表示,但線性表的數據是從1開始的,數組的元素是從0開始的。
2、線性表的順序存儲結構,在存、讀哪個數據的時候,不管在哪個位置,時間復雜度都是O(1),而在插入和刪除時,時間復雜度時O(n)。
3、線性表的優點:無需為表示表中元素之間的邏輯關系而增加額外的存儲空間;可以快速的存取表中的任意一個位置的元素。
4、線性表的缺點:插入和刪除數據時需要移動大量的數據;當線性表長度變化較大時,難以確定存儲空間的容量;容易造成存儲空間的 ”碎片“
Java代碼實現見下一篇。
