數據結構線性表的動態分配順序存儲結構算法c語言具體實現和算法時間復雜度分析


#include<stdio.h>
#include<stdlib.h>
//線性表的動態分配順序存儲結構
#define LIST_INIT_SIZE 100//線性表存儲空間的初始分配量
#define LISTINCREMENT 10//線性表存儲空間的分配增量
//函數結果狀態代碼
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;//Status是函數的類型,其值是函數結果狀態代碼
typedef int ElemType;
//線性表的動態分配順序存儲結構
typedef struct{
    ElemType *elem;//存儲空間基址
    int length;//當前長度
    int listsize;//當前分配的存儲容量的(以sizeof(ElemType)為單位)
}SqlList;

//構造一個空的線性表L
//O(1)
Status InitList_Sq(SqlList &L)
{
    //構造一個空的線性表
    L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
    if(!L.elem)
        {
            printf("線性表L構造失敗!\n");
            exit(OVERFLOW);//存儲分配失敗
        }
    L.length=0;//空表的長度為0
    L.listsize=LIST_INIT_SIZE;//初始的存儲容量
    printf("線性表L構造成功!\n");
    return OK;
}//InitList_Sq
//銷毀線性表L
//O(1)
Status DestroyList_Sq(SqlList &L)
{
    if(L.elem!=NULL)
    {
        free(L.elem);
        L.elem=NULL;
        L.length=0;
        L.listsize=0;
        printf("銷毀線性表L成功\n");
        return OK;
    }else
    {
        printf("線性表L不存在\n");    
    }
    return ERROR;
}//DestroyList_Sq
//將L重置為空表
//O(1)
Status ClearList_Sq(SqlList &L)
{
    if(L.elem!=NULL)
    {
        L.length=0;
        printf("已將線性表重置為空表!\n");
        return OK;
    }else
    printf("線性表重置為空表失敗!\n");
    return ERROR;
}//ClearList_Sq
//若L為空表,則返回TRUE,否則返回FALSE
//O(1)
Status ListEmpty_Sq(SqlList L)
{
    if(L.elem!=NULL&&L.length==0)
    {
        printf("線性表L為空表\n");
        return TRUE;
    }else if(L.elem!=NULL)
    {
        printf("線性表L不為空表\n");
        return FALSE;
    }else{
        printf("線性表L不存在\n");
        return FALSE;
    }
}//ListEmpty_Sq
//返回L中數據元素的個數
//o(1)
Status ListLength_Sq(SqlList L)
{
    if(L.elem!=NULL)
    {
        printf("線性表L的長度為%d\n",L.length);
        return L.length;
    }else
    printf("線性表L不存在");
    return -1;
}//ListLength_Sq
//用e返回L中第i個元素的值
//O(1)
void GetElem_Sq(SqlList L,int i,ElemType &e)
{
    if(L.elem!=NULL)
    {
        if(i<1||i>L.length)
            printf("訪問位置非法");
        else
        {
            e=L.elem[i-1];
        }
    }else
    printf("線性表L不存在");    
}//GetElem_Sq
//返回L中第一個與e滿足關系compare()的元素的位序。若這樣的數據元素不存在,則返回值為0
//O(n)
Status LocateElem_Sq(SqlList L,ElemType e,Status (*compare)(ElemType,ElemType))
{
    int i=1;
    ElemType *p=L.elem;
    if(L.elem!=NULL)
    {
        while(i<=L.length&&!(*compare)(*p++,e))
        {
            ++i;
        }
        if(i<=L.length)
        {
            printf("找到元素e在線性表L的位置為第%d個",i);
            return i;
        }else
        {
            printf("線性表L中不存在元素e");
            return 0;
        }
    }else
    printf("線性表L不存在");
    return 0;
}//LocateElem_Sq
//若cur_e是L的數據元素,且不是第一個,則用pre_e返回它的前驅,否則失敗,pre_e無定義
//O(n)
Status PriorElem_Sq(SqlList L,ElemType cur_e,ElemType *pre_e)
{
    int i=2;
    if(L.elem!=NULL)
    {
        while(i<=L.length)
        {
            if(cur_e==L.elem[i-1])
                *pre_e=L.elem[i-2];
                ++i;
                return OK;

        }
        return ERROR;
    }else
    printf("線性表L不存在");
    return ERROR;
}//PriorElem_Sq
//若cur_e是L的數據元素,且不是最后一個,則用next_e返回它的后繼,否則操作失敗,next_e無定義
//O(n)
Status NextElem_Sq(SqlList L,ElemType cur_e,ElemType *next_e)
{
    int i=1;
    if(L.elem!=NULL)
    {
        while(i<=L.length-1)
        {
            if(cur_e==L.elem[i-1])
                *next_e=L.elem[i];
                ++i;
                return OK;
        }
        return ERROR;
    }else
    printf("線性表L不存在");
    return ERROR;
}//NextElem_Sq
//在L中第i個位置之前插入新的數據元素e,L的長度加1
//一般情況下,在第i(1<=i<=n)個元素之前插入一個元素時,需要將第n至第i(共n-i+1)個元素向后移動一個位置
//假如pi是在第i個元素之前插入一個元素的概率,則在長度為n線性表中插入一個元素時所需移動元素的期望值(平均次數)為E(is)=pi(n-i+1),(i從1到n+1的和式)。
//不失一般性,我們可以假定在線性表的任何位置上插入,即,pi=1/(1+n),則上式可簡化為,E(is)=n/2。可見在順序存儲結構的線性表插入一個元素,平均約移動表中一半元素。若表長為n,則這個算法的時間復雜度為O(n)。
Status ListInsert_Sq(SqlList &L,int i,ElemType e)
{
    if(L.elem!=NULL)
    {
        if(i<1||i>L.length+1) return ERROR;
        if(L.length>=L.listsize)
        {
            ElemType *newbase=(ElemType *)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));
            if(!newbase)
            {
                exit(OVERFLOW);//存儲分配失敗
            }
            L.elem=newbase;//新基址
            L.listsize+=LISTINCREMENT;//增加存儲容量
        }
        ElemType *q,*p;
        q=&L.elem[i-1];
        for(p=&L.elem[L.length-1];p>=q;p--) *(p+1)=*p;//插入位置及以后元素后移
        *q=e;//插入e
        ++L.length;//表長增1
        return OK;
    }else
    printf("線性表L不存在");
    return ERROR;
}//ListInsert_Sq
//刪除L的第i個數據元素,並用e返回其值,L的長度減1
//一般情況下,刪除第(1<=i<=n)個元素時需從第i+1至第n個(共n-i)個元素依次向前移動一個位置
//假如qi是在第i個刪除第i個元素的概率,則在長度為n的線性表中刪除一個元素時所需移動元素的次數的期望(平均次數為)E(dl)=qi(n-i),(i從n的和式)。
//不失一般性,我們可以假定在線性表的任何位置上刪除元素都是等概率的,即qi=1/n,則上式可簡化為,E(dl)=(n-1)/2。可見在順序存儲結構的線性表刪除一個元素,平均約移動表中一半元素。若表長為n,則這個算法的時間復雜度為O(n)。
Status ListDelete_Sq(SqlList &L,int i,ElemType &e)
{
    if(L.elem!=NULL)
    {
        if(i<1||i>L.length) return ERROR;//i的位置不合法
        ElemType *p,*q;
        p=&L.elem[i-1];//p為被刪除元素的位置
        e=*p;//被刪除的元素賦給e
        q=L.elem+L.length-1;//表尾元素的位置
        for(++p;p<=q;++p) *(p-1)=*p;//被刪除元素之后的元素左移
        --L.length;
        return OK;
    }else
    printf("線性表L不存在");
    return ERROR;
}//ListDelete_Sq
//依次對L的每個數據元素調用函數visit().一旦visit失敗,則操作失敗
//O(n)
void ListTraverse_Sq(SqlList L,Status (*visit)(ElemType))
{
    if(L.elem!=NULL)
    {
        if(L.length==0)
        {
            printf("線性表為空\n");
        }else
        {
            for(int i=1;i<=L.length;i++)
            {
                if((*visit)(L.elem[i-1]))
                {
                
                }
                else
                {
                    printf("數據遍歷失敗");
                    return;
                }
            }
            printf("線性表為:");
            for(int i=1;i<=L.length;i++)
            {
                printf("%d,",L.elem[i-1]);
            }
        }
    }else
    {
        printf("線性表L不存在\n");
    }
}//ListTraverse_Sq
//L中第i個元素賦值同e的值
//O(1)
Status PutElem_Sq(SqlList L,int i,ElemType &e)
{
    if(L.elem!=NULL)
    {
        if(i<1||i>L.length)
        {
            printf("賦值在線性表中的位置非法\n");
            return ERROR;
        }else{
            L.elem[i-1]=e;
            return OK;
        }
    }
    else
    {
        printf("線性表L不存在\n");
        return ERROR;
    }
}//PutElem_Sq
//兩個順序表合並
//O(La.length+Lb.length)
void MergeList_Sq(SqlList La,SqlList Lb,SqlList &Lc)
{
    //已知順序線性表La和Lb的元素按值非遞減排列
    //歸並La和Lb得到新的順序線性表Lc,Lc的元素也按值非遞減排列
    ElemType *pa=La.elem;
    ElemType *pb=Lb.elem;
    Lc.listsize=Lc.length=La.length+Lb.length;
    ElemType *pc=Lc.elem=(ElemType *)malloc(Lc.listsize*sizeof(ElemType));
    if(!Lc.elem) exit(OVERFLOW);//存儲分配失敗
    ElemType *pa_last=La.elem+La.length-1;
    ElemType *pb_last=Lb.elem+Lb.length-1;
    while(pa<=pa_last&&pb<=pb_last)
    {
        if(*pa<=*pb)*(pc++)=*(pa++);
        else *(pc++)=*(pb++);
    }
    while(pa<=pa_last) *(pc++)=*(pa++);//插入La的剩余元素
    while(pb<=pb_last) *(pc++)=*(pb++);//插入Lb的剩余元素
}//MergeList_Sq
int main()
{
    SqlList L,La,Lb,Lc;
    ElemType i,e;
    //初始化線性表
    InitList_Sq(L);
    InitList_Sq(La);
    InitList_Sq(Lb);
    for(i=1;i<=LISTINCREMENT;i++)
    {
        ListInsert_Sq(La,i,i);
        ListInsert_Sq(Lb,i,i+1);
    }
    MergeList_Sq(La,Lb,Lc);
    printf("線性表La中的元素為:");
    for(i=1;i<=La.length;i++)
    {
        GetElem_Sq(La,i,e);
        printf("%d,",e);
    }
    printf("\n線性表La中的元素為:");
    for(i=1;i<=Lb.length;i++)
    {
        GetElem_Sq(Lb,i,e);
        printf("%d,",e);
    }
    printf("\n線性表Lc中的元素為:");
    for(i=1;i<=Lc.length;i++)
    {
        GetElem_Sq(Lc,i,e);
        printf("%d,",e);
    }
    DestroyList_Sq(La);
    DestroyList_Sq(Lb);
    DestroyList_Sq(Lc);
    /*for(i=1;i<=LISTINCREMENT;i++)
    {
        L.elem[i-1]=i;
        L.length++;
    }*/
    //給線性表賦值
    /*for(i=1;i<=LISTINCREMENT;i++)
    {
        ListInsert_Sq(L,i,i);
    }*/
    /*printf("線性表中的元素為:");
    for(i=1;i<=LISTINCREMENT;i++)
    {
        GetElem_Sq(L,i,e);
        printf("%d,",e);
    }*/
    /*printf("線性表L元素為:");
    //直接給線性表賦值,有可能會產生溢出現象,如果下標超出內存分配上屆
    for(i=1;i<=LISTINCREMENT;i++)
    {
        printf("%d,",L.elem[i-1]);
    }*/
    //遍歷整個線性表L
    //ListTraverse_Sq(L);
    //得到線性表長度
    ListLength_Sq(L);
    //判斷線性表是否為空
    ListEmpty_Sq(L);
    //清空線性表中的數據
    ClearList_Sq(L);
    //銷毀整個線性表
    DestroyList_Sq(L);
    //清空線性表中的數據
    ClearList_Sq(L);
    getchar();
    getchar();
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM