1.顺序表

1.1 顺序表基本概念

顺序表十分简单,简明扼要两句话

  • 逻辑上:线性结构
  • 物理上:地址连续的存储单元

1.2 顺序表构造

顺序表用结构体来定义

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

顺序表的基本功能如下:

  • 初始化
  • 定位数据
  • 获取长度
  • 获取数据
  • 插入数据
  • 删除数据
  • 判空
  • 销毁

写成接口,至于参数为啥这么给的,得看后面的具体实现了。

/* base functions */
// init function
bool InitList(SqList *L);

//get length
int Length(SqList L);

//locate data
int LocateElem(SqList L, ElemType e);

//get data
ElemType GetElem(SqList L, int i);

// insert data
bool ListInsert(SqList *L, int i, ElemType e);


// delete data
bool ListDelete(SqList *L, int i, ElemType *e);

//print data
bool PrintList(SqList L);

//wheater list is empty
bool Empty(SqList L);

// clear all the data
bool DestroyList(SqList *L);

1.3 顺序表实现

开始之前, 先为了程序看起来更加人性化,定义一些便于理解的宏变量。

#define ElemType int
#define MaxSize 50
#define InitSize 100
#define bool short
#define true 1
#define false 0

1.3.1 初始化

使用动态申请内存的方式初始化顺序表,若初始化失败则退出。
初始化顺序表长度为0。

bool InitList(SqList *L){
    L->data = (ElemType*)malloc(InitSize * sizeof(ElemType));
    if(!L->data)
        exit(-1);
    L->length = 0;

    return true;
}

1.3.2 定位数据

根据数据按顺序往下找就完事了,找到了返回位置,找不到就返回0, 注意第一个位置是1。

int LocateElem(SqList L, ElemType e){
    int i;
    for(int i=0; i < L.length; ++i){
        if(L.data[i] == e)
            return i+1;
    }
    return 0;
}

1.3.3 获取长度

int Length(SqList L){
    return L.length;
}

1.3.4 获取数据

根据位置返回数据。

ElemType GetElem(SqList L, int i){
    return L.data[i];
}

1.3.5 插入数据

根据位置插入数据。
如果位置超过返回,直接返回失败;
从当前顺序表中的最后一个数据的后面(注意顺序表的长度length指向最后一个数据的后面)开始,依次将数据往后挪,直到需要插入的位置为止。
插入后将长度加1。

bool ListInsert(SqList *L, int i, ElemType e){
    if(i < 1 || i > L->length+1) 
        return false;

    if(L->length >= MaxSize)
        return false;

    for(int j=L->length; j >= i; j--)
        L->data[j] = L->data[j-1];
    L->data[i-1]=e;
    L->length++;
    return true;
}

1.3.6 删除数据

首先进行合理性检测,检查位置是否在范围内。
将要删除的数据赋值返回。
从删除的位置开始依次将数据往前挪,最后将长度减1。

bool ListDelete(SqList *L, int i, ElemType *e){
    if(i < 1 || i > L->length)
        return false;

    *e = L->data[i-1];
    for(int j=i; j < L->length; ++j)
        L->data[j-1] = L->data[j];
    L->length--;
    return true;
}

1.3.7 判空

这里使用了三目运算符。

bool Empty(SqList L){
    return L.length == 0?true:false;
}

1.3.8 销毁

释放指针所指的内存即可,注意将指针指空,并把长度设为0。

bool DestroyList(SqList *L){
    free((L->data));

    L->data = NULL;
    L->length = 0;
    return true;
}

1.3.9 测试

为了测试方便再加个打印函数。

bool PrintList(SqList L){
    for(int i = 0; i < L.length; ++i)
        printf("%d ", L.data[i]);
    printf("
");
    return true;
}

完整测试代码如下,对顺序表进行上述功能测试。

int main(){
    SqList L;
    ElemType e = 4;

    printf("Initialize List...
");
    InitList(&L);
    
    printf("Insert data...
");
    for(int i = 1; i <= 6; ++i)
        ListInsert(&L, i, 2*i);

    printf("List==>");
    PrintList(L);

    printf("Get length...
");
    int len = Length(L);
    printf("Length==>%d
", len);

    printf("locate data...
");
    int loc = LocateElem(L, e);
    printf("locate at {%d}
", loc);

    printf("Get data...
");
    int elem = GetElem(L, 1);
    printf("Get data==>%d
", elem);

    printf("delete data...
");
    int del;
    ListDelete(&L, loc, &del);
    printf("Delete Data==>%d
", del);
    printf("List==>");
    PrintList(L);

    DestroyList(&L);
    bool isEmpty = Empty(L);
    if(isEmpty) printf("Empty!
");

    return 0;
}

1.4 顺序表应用

  1. 从顺序表删除最小元素(假设唯一)并返回该值,空出的位置由最后一个元素填补。
    过于简单不做分析。
bool Del_Min(SqList *L, ElemType *value){
    if(!L->length)
        return false;

    int min = 0;
    for(int i = 1; i < L->length; ++i){
        if(L->data[min] > L->data[i])
            min = i;
    }
    *value = L->data[min];
    L->data[min] = L->data[--L->length];
    return true;
}

2.将顺序表逆置,空间复杂度要求O(1)。
分别从头尾开始,交换每个数据。

bool ReverseList(SqList *L){
    if(!L->length)
        return false;

    for(int i=0, j=L->length-1; i < j; ++i,--j){
        swap(&L->data[i], &L->data[j]);
    }
    return true;
}

3.对长度为n的顺序表L, 删除L中所有值为x的数据元素。
方法一:将顺序表中不等于x的值按顺序保存,用k记录不等于k的个数,最后修改长度为k。

bool Del_x_1(SqList *L, ElemType x){
    int k = 0;
    for(int i = 0; i < L->length; ++i){
        if(L->data[i] != x)
            L->data[k++] = L->data[i];
    }
    L->length = k;
    return true;
}

方法二:用k记录顺序表中等于k的值,并把不等于k的值向前移动k个位置,最后修改长度为length-k。

bool Del_x_2(SqList *L, ElemType x){
    int k = 0;
    for(int i = 0; i < L->length; ++i){
        if(L->data[i] == x)
            k++;
        else
            L->data[i-k] = L->data[i];
    }
    L->length -= k;
    return true;
}

4.删除有序顺序表中s与t之间(s<t)的所有元。
这个题和第3题有异曲同工之妙,按下不表。

/*
同第三题方法一,将L中小于等于s,大于等于t的值按顺序保存, 用k记录不等于x的个数,最后长度修改为k。
*/
bool Del_s_t_1(SqList *L, ElemType s, ElemType t){
    if(s >= t || L->length == 0)
        return false;

    int k = 0;
    for(int i = 0; i < L->length; ++i){
        if(L->data[i] <= s || L->data[i] >= t)
            L->data[k++] = L->data[i];
    }
    L->length = k;
    return true;
}


/*
由于是有序表,只需要找到大于等于s的第一个元素与大于等于t的第一个元素,将删除这段,只需将后面的元素前移。
*/
bool Del_s_t_2(SqList *L, ElemType s, ElemType t){
    if(s >= t || L->length == 0)
        return false;

    int i, j;
    for(i = 0; i < L->length && L->data[i] < s; ++i);
    if(i == L->length) return false;

    for(j = i; i < L->length && L->data[j] < t; ++j);
    if(j == L->length) return false;

    for(; j < L->length; ++i, ++j)
        L->data[i] = L->data[j];
    L->length = i;
    return true;
 }

6.从有序表中删除重复的元素。
注意是有序表,数据只会连续重复出现。
设置一个flag,用来标记当前数据,把接下的数据

原文地址:https://www.cnblogs.com/hichens/p/14982369.html