1. 程式人生 > >順序表中基本操作的實現

順序表中基本操作的實現

//庫函式標頭檔案包含
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

//函式狀態碼定義
#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE -1
#define OVERFLOW   -2

typedef int  Status;

//順序表的儲存結構定義
#define LIST_INIT_SIZE  100
#define LISTINCREMENT   10
typedef int ElemType; //假設線性表中的元素均為整型 typedef struct//注意這裡的寫法 { ElemType* elem; //儲存空間基地址 int length; //表中元素的個數 int listsize; //表容量大小 } SqList; //順序表型別定義

一、順序表的初始化

Status InitList_Sq(SqList &L)
{
    L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));//注意是給L.elem分配空間//在初始化的時候,有長度限制,因為是順序結構
    if
(!L.elem) exit(OVERFLOW); L.length=0; L.listsize=LIST_INIT_SIZE; }

注意: (1)是給L.elem分配空間,而不是L,不要和連結串列混淆 (2)在給L.elem分配空間的時候,LIST_INIT_SIZE*sizeof(ElemType),會有具體的長度,因為是順序結構,有明確的長度,不要和連結串列混淆,連結串列才沒有具體的長度 (3)在初始化的時候,順序表長度為0,容量大小為分配空間的大小

演算法時間複雜度:O(1)

二、順序表的建立

Status ListCreate_Sq(SqList &L)
{ ElemType n,m; scanf("%d",&n); L.elem=(ElemType*)malloc(n*sizeof(ElemType));//雖然之前已經確定了分配的空間,但是,之後因為有確定的數字了,所以重新分配空間; if(!L.elem) exit(OVERFLOW); L.length=n; L.listsize=n; for(int i=0; i<n; i++) { scanf("%d",&m); L.elem[i]=m; //scanf("%d",&L.elem[i]);//這種方法也是對的 } return OK; }

ListCreate_Sq 和 InitList_Sq是不同的,InitList_Sq是結構初始化,初始化的時候,L.length=0;L.listsize=LIST_INIT_SIZE。ListCreate_Sq 是建立一個順序表,L.length和L.listsize由輸入的值確定。但是兩者還是有共同點的,兩者都先L.elem=(ElemType*)malloc(....*sizeof(ElemType)); 一般是先InitList_Sq(La);然後再CreateList_Sq(La);

三、順序表的插入

1、指定插入位置

方法1:

Status ListInsert_Sq(SqList &L, int pos, ElemType e)//插入必須要看空間問題,不夠的話就重新分配,倒著賦值//注意pos是位置,從1開始的
{
    ElemType* newbase;
    if(pos>=1&&pos<=L.length+1)//pos是位置,別忘記對length+1length為元素的個數),因為可以插入的位置有n+1個;
    {
        if(L.length>=L.listsize)//這裡別忘記等於號,因為等於的話,再插入也會超過記憶體大小;
        {
            newbase=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));//與LISTINCREMENT相加的是listsize而不是length,因為是增大記憶體//給newbase動態分配一個長度為LISTINCREMENT的新空間
            if(!newbase) exit(OVERFLOW);//在分配空間方面,都要進行這樣的判斷;
            L.elem=newbase;//新分配空間的基地址
            L.listsize+=LISTINCREMENT;//重新分配空間了,所以別忘記改變容量的大小。
        }
        for(int i=L.length;i>=pos;i--)
            L.elem[i]=L.elem[i-1];
        L.elem[pos-1]=e;
        L.length++;//多了一個數據元素,所以length也要加一;
        return OK;
    }
    else  return ERROR;//別忘記else
}

方法2:

Status ListInsert_Sq(SqList &L,int pos,ElemType e)//在pos位置插入e元素
{
    ElemType* newbase;//newbase是ElemType*類型的,別定義錯了
    if(pos>=1&&pos<=L.length+1)//可以插入的有n+1個位置,所以,別忘了+1//pos是位置,別忘記對length+1length為元素的個數),因為可以插入的位置有n+1個;
    {
        if(L.length>=L.listsize)//這裡別忘記等於號,因為等於的話,再插入也會超過記憶體大小;
        {
            newbase=(ElemType*)realloc(L.elem,(LISTINCREMENT+L.listsize)*sizeof(ElemType));//注意是在L.listsize基礎上進行的擴充,因為是增大記憶體,
            if(!newbase) exit(OVERFLOW);//在分配空間方面,都要進行這樣的判斷;
            L.elem=newbase;
            L.listsize+=LISTINCREMENT;//重新分配空間了,所以別忘記改變容量的大小。
        }
        ElemType *p,*q;
        p=&(L.elem[pos-1]);
        for(q=&(L.elem[L.length-1]);q>=p;q--)
            *(q+1)=*q;
        *p=e;
        L.length++;
        return OK;
    }
    else  return ERROR;//別忘記else
}

注意: (1)對於在順序表中插入一個數來說,一定要先判斷插入的位置是否是在1—length+1的範圍內,在的話,看資料多少是否超過了儲存空間的大小,超過了的話,要進行空間重新分配,空間重新分配的時候還不要忘記判斷是否分配成功。成功的話,改變記憶體大小,然後將要插入的位置記錄下來,倒著賦值,賦值的時候注意臨界點的判斷,最後不要忘記長度加一。 (2)newbase到底是什麼型別的,自己要分清了 (3)重新分配的時候,是LISTINCREMENT+L.listsize與sizeof相乘 (4)別忘記對於地址的儲存

演算法的時間複雜度為:O( ListLength(L) )

2、給出一定的條件,插入資料 例如:有序插入函式,L是一個遞增的有序順序表,函式Status ListInsert_SortedSq(SqList &L, ElemType e)用於向順序表中按遞增的順序插入一個數據。 比如:原資料有:2 5,要插入一個元素3,那麼插入後順序表為2 3 5。 要考慮擴容的問題。

Status ListInsert_SortedSq(SqList &L, ElemType e)
{
    int i=0;
    for(int j=0;j<L.length;j++)
    {
        if(L.elem[j]>e)  break;//注意臨界判斷條件
        else i++;
    }
    for(int j=L.length; j>=i+1; j--)  L.elem[j]=L.elem[j-1];
    L.elem[i]=e;
    L.length++;//這裡不要忘記;
    return OK;
}

注意:

Status ListInsert_SortedSq(SqList &L, ElemType e)
{
    ElemType i=0;
    while(L.elem[i]<e)
    {
        i++;
    }
    for(int j=L.length-1;j>=i;j--)
        L.elem[j+1]=L.elem[j];
    L.elem[i]=e;
    L.length++;//這裡不要忘記;
    return OK;
}

這個是錯誤的,因為,萬一想要插入的數比所有的數都打的話,那麼i就會無限制地增加

改成

Status ListInsert_SortedSq(SqList &L, ElemType e)
{
    int i=0;
    while(L.elem[i]<e&&i<L.length)//千萬不要忘記i<L.length這個條件
    {
        i++;
    }
    for(int j=L.length-1;j>=i;j--)
        L.elem[j+1]=L.elem[j];
    L.elem[i]=e;
    L.length++;//這裡不要忘記;
    return OK;
}

注意:增加元素的同時,不要忘記將長度加1;

四、順序表的刪除 刪除pos位置處的元素,並給e賦值為pos位置處的元素 方法1:

Status ListDelete_Sq(SqList &L, int pos, ElemType &e)
{
    if(pos>=1&&pos<=L.length)
    {
        e=L.elem[pos-1];
        for(int i=pos-1;i<=L.length-2;i++)
            L.elem[i]=L.elem[i+1];
        L.length--;
    }
    else  return ERROR;
}

方法2:

Status ListDelete_Sq(SqList &L, int pos, ElemType &e)//刪除不用考慮空間問題,一個個前移就好,最後別忘記L.length--
{
    if(pos>=1&&pos<=L.length)
    {
        ElemType *p;
        e=L.elem[pos-1];//先將e賦值,也就是返回刪掉了哪個數
        for(p=&(L.elem[pos-1]);p<=&(L.elem[L.length-2]);p++)
            *p=*(p+1);
        L.length--;
    }
    else  return ERROR;
}

注意: (1)刪除元素的同時,不要忘記將長度減1; (2)刪除是正向賦值,插入是倒敘賦值

演算法的時間複雜度為:O( ListLength(L) )

五、查詢某元素的位置

查詢元素e在順序表的位次並返回

int ListLocate_Sq(SqList L, ElemType e)
{
    int a=-1;
    int i;
    for(i=0; i<L.length; i++)
    {
        if(L.elem[i]==e)
        {
            a=1;
            break;
        }
        else  continue;
    }
    if(a==-1)
    {
        return 0;
    }
    else return i+1;
}

六、對於符合某條件的元素的定位

Status Equal(ElemType a,ElemType b)
{
    if(a==b)  return true;
    else  return false;
}
int LocateElem_Sq(SqList L,ElemType e,Status(*compare)(ElemType,ElemType))//在表中查詢第一個值與e滿足compare()的元素的位序
{
    ElemType *p;
    int i=1;//i的初值為第1個元素的位序
    p = L.elem; //p的初值為第1個元素的儲存位置
    while(i <= L.length && !(* compare)(*p++,e)) i++;
    if(i <= L.length) return i;
    else return 0;
}

/////////////////////////////////用法
if(!LocateElem_Sq(La,elem,Equal))
            ListInsert_Sq(Lc,Lc.length+1,elem);

演算法的時間複雜度為:O( ListLength(L) )