002--數據結構與算法(線性表)

前言

線性結構的基本特色是除了第一個元素無直接前驅,最後一個元素無直接後續以外,其餘每一個數據元素都有一個前驅和後繼. 線性表是最基本且最經常使用的一種線性結構,同時它也是其餘的數據結構的基礎. 尤爲是單鏈表是貫穿於整個數據結構課程的基本技術點.算法

一. 線性表的定義和特色

在咱們生活中有那些線性表的例子了?數組

例如,26個字母表; 例如學生基本信息表.每一個學生爲一個數據元素,包含學號,姓名,專業等數據項目.bash

知足數據元素不一樣,可是在同一個線性表中的元素一定具備相同的特色,即屬於同一數據對象, 相鄰數據元素之間存在這個序偶關係. 諸如此類由(n>=0)個數據特性相同的元素構成的有限序列稱爲"線性表".數據結構

線性表中的元素的個數n定義爲線性表的長度,若是n = 0則稱爲空表.函數

對於非空的線性表和線性結構,其特色以下:學習

  • 存在惟一的一個被稱做"第一個"的數據元素
  • 存在惟一的一個唄稱做"最後一個"的數據元素
  • 除了第一個以外,結構中的每一個數據元素均有一個前驅
  • 除了最後一個以外,結構中的每一個數據元素都有一個後繼.

1.2 線性表的類型定義

線性表是一個至關靈活的數據結構,其長度可根據須要增加或縮短,即對線性表的數據元素不只能夠進行訪問,並且能夠對其進行插入和刪除等操做.ui

ADT List{
 	Data: 線性表的數據對象集合爲{a1,a2,......an},每一個元素的類型均爲DataType. 其中,除了第一個元素a1外,每個元素有且只有一個直接前驅元素,除了最後一個元素an外,每一個元素有且只有一個直接後繼元素. 數據元素之間的關係是一對一的關係.
 	
Operation
	InitList(&L) 
	操做結果:初始化操做,創建一個空的線性表L.
	
	DestroyList(&L) 
	初始條件: 線性表L已存在
	操做結果: 銷燬線性表L.
	
	ClearList(&L)
	初始條件: 線性表L已存在
	操做結果: 將L重置爲空表.
	
	ListEmpty(L)
	初始條件: 線性表L已存在
	操做結果: 若L爲空表,則返回true,不然返回false.
	
	ListLength(L)
	初始條件: 線性表L已存在
	操做結果: 返回L中數據元素的個數
	
	GetElem(L,i,&e)
	初始條件: 線性表L已存在,且1<=i<ListLength(L)
	操做結果: 用e返回L中第i個數據元素的值;
	
	LocateElem(L,e)
	初始條件: 線性表L已存在
	操做結果: 返回L中第1個值與e相同的元素在L中的位置. 若數據不存在則返回0;
	
	PriorElem(L,cur_e,&pre_e);
	初始條件: 線性表L已存在
	操做結果: 若cur_e是L的數據元素,且不是第一個,則用pre_e返回其前驅,不然操做失敗.
	
	NextElem(L,cur_e,&next_e);
	初始條件: 線性表L已存在
	操做結果: 若cur_e是L的數據元素,且不是最後一個,則用next_e返回其後繼,不然操做失敗.
	  	
	ListInsert(L,i,e);
	初始條件: 線性表L已存在,且1<=i<=listLength(L)
	操做結果: 在L中第i個位置以前插入新的數據元素e,L長度加1.
	
	ListDelete(L,i);
	初始條件: 線性表L已存在,且1<=i<=listLength(L)
	操做結果: 刪除L的第i個元素,L的長度減1.
	
	TraverseList(L);
	初始條件: 線性表L已存在
	操做結果: 對線性表L進行遍歷,在遍歷的過程當中對L的每一個結點訪問1次.	
	
}ADT List.
複製代碼

1.3 線性表的順序表示與實現

1.3.1 線性表的順序存儲表示

線性表的順序表示指的是一組地址連續的存儲單元依次存儲線性表的數據元素,這種表示也稱爲線性表的順序存儲結構或順序映像. 一般,稱這種存儲結構的線性表爲順序表(Sequential List). 其特色是, 邏輯上相鄰的數據元素,其物理次序也是相鄰的.spa

順序表的存儲結構code

#define MAXSIZE 100
#define ElemType int

typedef struct {
    ElemType *data;
    int length;
}Sqlist;

複製代碼

1.3.2 順序表的基本操做的實現

算法1.1 順序表的初始化

順序表的初始化就是構成一個空的順序表; 算法步驟:對象

  1. 爲順序表L動態分配一個預約義大小的數組空間,使elem 指向這段空間的基地址;
  2. 將表的當前長度設置爲0;

算法實現

//初始化
Status InitList(Sqlist *L){
    //爲順序表分配一個大小爲MAXSIZE 的數組空間
    L->data =  malloc(sizeof(ElemType) * MAXSIZE);
    //存儲分配失敗退出
    if(!L->data) exit(ERROR);
    //空表長度爲0
    L->length = 0;
    return OK;
}
複製代碼

main函數調用

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, Data Structure!\n");
    
    Sqlist L;
    Sqlist Lb;
    ElemType e;
    Status iStatus;
    int j,k;
    
    iStatus = InitList(&L);
    printf("初始化L後: L.Length = %d\n", L.length);
    
    
    return 0;
}
複製代碼

結果

Hello, Data Structure!
初始化L後: L.Length = 0
Program ended with exit code: 0
複製代碼
算法1.2 順序表插入

算法步驟:

  1. 判斷插入位置i是否合法(i值的合法範圍1<=i<n+1),若不合法則返回ERROR;
  2. 判斷順序表的存儲空間是否已滿,若滿則返回ERROR;
  3. 將第n個至第i個位置的元素依次向後移動一個位置,空出第i個位置(i = n+1)時無須要移動;
  4. 將要插入的新元素e放入第i個位置;
  5. 表長累積1.

算法實現:

//1.2 順序表的插入
/*
 初始條件:順序線性表L已存在,1≤i≤ListLength(L);
 操做結果:在L中第i個位置以前插入新的數據元素e,L的長度加1
 */
Status ListInsert(Sqlist *L,int i,ElemType e){
    
    //i值不合法判斷
    if((i<1) || (i>L->length+1)) return ERROR;
    //存儲空間已滿
複製代碼
if(L->length == MAXSIZE) return ERROR;
 
    //插入數據不在表尾,則先移動出空餘位置
    if(i <= L->length){
        for(int j = L->length-1; j>=i-1;j--){
       
            //插入位置以及以後的位置後移動1位
            L->data[j+1] = L->data[j];
        }
    }
    
    //將新元素e 放入第i個位置上
    L->data[i-1] = e;
    //長度+1;
    ++L->length;
    
    return OK;
    
}

複製代碼

main函數調用

int main(int argc, const char * argv[]) {
	...
   //1.2 順序表數據插入
    for(int j=1; j <= 5;j++){
        iStatus = ListInsert(&L, 1, j);
    }
    printf("插入數據L長度: %d\n",L.length);
    
  }
複製代碼

結果

Hello, Data Structure!
初始化L後: L.Length = 0
插入數據L長度: 5
Program ended with exit code: 0
複製代碼
算法1.3 順序表取值

算法步驟

  1. 判斷指定的位置序號i是否合理(1<=i<L.length),若不合理,則返回ERROR;
  2. 若i值合理,則將第i個數據元素L.data[i-1]賦值給參數e, 經過e返回第i個數據元素的傳值.
//1.2 順序表的取值
Status GetElem(Sqlist L,int i, ElemType *e){
    //判斷i值是否合理, 若不合理,返回ERROR
    if(i<1 || i > L.length) return  ERROR;
    //data[i-1]單元存儲第i個數據元素.
    *e = L.data[i-1];
    
    return OK;
}
複製代碼

main函數調用

int main(int argc, const char * argv[]) {
	...
   //1.3 順序表取值
    GetElem(L, 5, &e);
    printf("順序表L第5個元素的值爲:%d\n",e);
    
  }
複製代碼

結果

Hello, Data Structure!
初始化L後: L.Length = 0
插入數據L長度: 5
順序表L第5個元素的值爲:1
Program ended with exit code: 0
複製代碼
算法1.4 順序表刪除

算法步驟

  1. 判斷刪除位置i的合法(合法值 1 <= i <=n),若不合法則返回ERROR;
  2. 判斷線性表是否爲空
  3. 將第 i+1 個至第 n 個的元素依次向前移動一個位置( i=n 時無需移動)
  4. 表長減1;

算法實現:

//1.4 順序表刪除指定元素
/*
 初始條件:順序線性表L已存在,1≤i≤ListLength(L)
 操做結果: 刪除L的第i個數據元素,L的長度減1
 */
Status ListDelete(Sqlist *L,int i){
    
    //線性表爲空
    if(L->length == 0) return ERROR;
    
    //i值不合法判斷
    if((i<1) || (i>L->length+1)) return ERROR;
    
    for(int j = i; j < L->length -1 ;j++){
        //被刪除元素以後的元素向前移動
        L->data[j-1] = L->data[j];
    }
    //表長度-1;
    L->length --;
    
    return OK;
    
}


複製代碼

main函數調用

int main(int argc, const char * argv[]) {
	...
   //1.4 順序表刪除第2個元素
    ListDelete(&L, 2);
    printf("順序表刪除第%d元素,長度爲%d\n",2,L.length);
    
  }
複製代碼

結果

Hello, Data Structure!
初始化L後: L.Length = 0
插入數據L長度: 5
順序表L第5個元素的值爲:1
順序表刪除第2元素,長度爲4
Program ended with exit code: 0
複製代碼

二.繼續探索

你們能夠根據文章前面的學習,完成如下的需求!

2.1 問題

ClearList(&L)
	初始條件: 線性表L已存在
	操做結果: 將L重置爲空表.
	
	ListEmpty(L)
	初始條件: 線性表L已存在
	操做結果: 若L爲空表,則返回true,不然返回false.
	
	ListLength(L)
	初始條件: 線性表L已存在
	操做結果: 返回L中數據元素的個數
	
	TraverseList(L);
	初始條件: 線性表L已存在
	操做結果: 對線性表L進行遍歷,在遍歷的過程當中對L的每一個結點訪問1次.

	LocateElem(L,e)
	初始條件: 線性表L已存在
	操做結果: 返回L中第1個值與e相同的元素在L中的位置. 若數據不存在則返回0;
	
	PriorElem(L,cur_e,&pre_e);
	初始條件: 線性表L已存在
	操做結果: 若cur_e是L的數據元素,且不是第一個,則用pre_e返回其前驅,不然操做失敗.
	
	NextElem(L,cur_e,&next_e);
	初始條件: 線性表L已存在
	操做結果: 若cur_e是L的數據元素,且不是最後一個,則用next_e返回其後繼,不然操做失敗.

複製代碼

2.2 參考答案

//1.5 清空順序表
/* 初始條件:順序線性表L已存在。操做結果:將L重置爲空表 */
Status ClearList(Sqlist *L)
{
    L->length=0;
    return OK;
}

//1.6 判斷順序表清空
/* 初始條件:順序線性表L已存在。操做結果:若L爲空表,則返回TRUE,不然返回FALSE */
Status ListEmpty(Sqlist L)
{
    if(L.length==0)
        return TRUE;
    else
        return FALSE;
}

//1.7 獲取順序表長度
/* 初始條件:順序線性表L已存在。操做結果:返回L中數據元素個數 */
int ListLength(Sqlist L)
{
    return L.length;
}

//1.8 順序輸出List
/* 初始條件:順序線性表L已存在 */
/* 操做結果:依次對L的每一個數據元素輸出 */
Status TraverseList(Sqlist L)
{
    int i;
    for(i=0;i<L.length;i++)
        printf("%d\n",L.data[i]);
    printf("\n");
    return OK;
}

//1.9 順序表查找元素並返回位置
/* 初始條件:順序線性表L已存在 */
/* 操做結果:返回L中第1個與e知足關係的數據元素的位序。 */
/* 若這樣的數據元素不存在,則返回值爲0 */
int LocateElem(Sqlist L,ElemType e)
{
    int i;
    if (L.length==0) return 0;
    
    for(i=0;i<L.length;i++)
    {
        if (L.data[i]==e)
            break;
    }
  
    if(i>=L.length) return 0;
    return i+1;
}

複製代碼
相關文章
相關標籤/搜索