【吉大刘大有数据结构绿皮书】已知长度为n的线性表A采用顺序存储结构,写一算法,删除该线性表中所有值为item的数据元素。

题目

已知长度为n的线性表A采用顺序存储结构,写一算法,删除该线性表中所有值为item的数据元素。

思路及解答

题目要求A时顺序表,并删除值为item的元素,一般的想法是遍历整个顺序表,每次遍历遇到值为item的元素后,就将后面的元素依次向前移动一格,保证值为item的元素所占内存被覆盖,间接删除,其C语言实现如下:

//删除顺序表中值为item的数据元素
void DeleteSeqList1(SeqList* A, int item)
{
    int n = A->len;//顺序表长度
    for (int i = 0; i < n; i++)
    {
        //找到要删除的元素后,将后面的元素依次向前移动
        if (A->data[i] == item)
        {
            //写到n-1避免越界
            for (int j = i; j < n-1; j++)
            {
                A->data[j] = A->data[j + 1];
            }
            A->len--;
        }
    }
}

由上述代码的双层循环可知,其算法时间复杂度明显为 O ( n 2 ) O(n^{2}) O(n2),如果考试要求事件复杂度较好的情况下完成这个算法,那么上面这个函数的时间复杂度很糟糕,我们要想办法换成时间复杂度更好的算法,尽量用一次循环就解决问题,设置变量m(初值为0)用于记录被删除元素的个数,n为顺序表的长度,如果循环遍历满足删除的条件,则让m=m+1,否则就让删除元素后面的元素依次向前移动m个内存单位(即data[i-m]=data[i],其算法的过程图示如下(已知顺序表(1,2,3,4,5,6,3,7),要删除的元素是3):
【吉大刘大有数据结构绿皮书】已知长度为n的线性表A采用顺序存储结构,写一算法,删除该线性表中所有值为item的数据元素。_第1张图片
【吉大刘大有数据结构绿皮书】已知长度为n的线性表A采用顺序存储结构,写一算法,删除该线性表中所有值为item的数据元素。_第2张图片
【吉大刘大有数据结构绿皮书】已知长度为n的线性表A采用顺序存储结构,写一算法,删除该线性表中所有值为item的数据元素。_第3张图片
【吉大刘大有数据结构绿皮书】已知长度为n的线性表A采用顺序存储结构,写一算法,删除该线性表中所有值为item的数据元素。_第4张图片
其对应的C语言代码如下:

//删除顺序表中值为item的数据元素
void DeleteSeqList(SeqList* A, int item)
{
    int n = A->len;//变量n是顺序表的长度
    int m = 0;//变量m记录了删除元素的个数,当删除后,每次循环时,都要将前面的元素向前移动m个格子确保删除
    for (int i = 0; i < n; i++)
    {
        if (A->data[i] == item)
        {
            m = m + 1;
        }
        else
        {
            A->data[i - m] = A->data[i];//删了多少元素,就将非删除的元素向前移动多少,保证没有空缺
        }
    }
    A->len = n - m;
}

由此可见,这种方法更好,因为它的算法时间复杂度为 O ( n ) O(n) O(n)
完整的测试代码如下:

#include 
#include
#define MaxSize 1000
//顺序存储结构的线性表
typedef struct SeqList {
    int len;//顺序表长度
    int data[MaxSize];//顺序存储结构
}SeqList;
//初始化
void InitSeqList(SeqList* L)
{
    L->len = 0;
}
//在下标为index的位置插入元素elem
void InsertSeqList(SeqList* L, int index, int elem)
{
    if (index<0 && index>L->len)
    {
        printf("下标越界!\n");
        return;
    }
    L->data[index] = elem;
    L->len++;
}
//尾插
void InsertTailSeqList(SeqList* L, int elem)
{
    if (L->len > MaxSize)
    {
        printf("已超过顺序表最大容量,无法插入!\n");
        return;
    }
    L->data[L->len] = elem;
    L->len++;
}
//打印顺序表
void printSeqList(SeqList* L)
{
    if (L->len == 0)
    {
        printf("顺序表空!\n");
    }
    for (int i = 0; i < L->len; i++)
    {
        printf("%d\t", L->data[i]);
    }
    printf("\n");
}
//删除顺序表中值为item的数据元素O(n)
void DeleteSeqList(SeqList* A, int item)
{
    int n = A->len;//变量n是顺序表的长度
    int m = 0;//变量m记录了删除元素的个数,当删除后,每次循环时,都要将前面的元素向前移动m个格子确保删除
    for (int i = 0; i < n; i++)
    {
        if (A->data[i] == item)
        {
            m = m + 1;
        }
        else
        {
            A->data[i - m] = A->data[i];//删了多少元素,就将非删除的元素向前移动多少,保证没有空缺
        }
    }
    A->len = n - m;
}
//删除顺序表中值为item的数据元素O(n^2)
void DeleteSeqList1(SeqList* A, int item)
{
    int n = A->len;//顺序表长度
    for (int i = 0; i < n; i++)
    {
        //找到要删除的元素后,将后面的元素依次向前移动
        if (A->data[i] == item)
        {
            //写到n-1避免越界
            for (int j = i; j < n-1; j++)
            {
                A->data[j] = A->data[j + 1];
            }
            A->len--;
        }
    }
}
int main()
{
    SeqList* L = (SeqList*)malloc(sizeof(SeqList));
    if (L == NULL)
    {
        printf("内存不足!\n");
        return 0;
    }
    InitSeqList(L);
    InsertTailSeqList(L, 1);
    InsertTailSeqList(L, 2);
    InsertTailSeqList(L, 3);
    InsertTailSeqList(L, 4);
    InsertTailSeqList(L, 5);
    InsertTailSeqList(L, 6);
    InsertTailSeqList(L, 3);
    InsertTailSeqList(L, 7);
    printSeqList(L);
    DeleteSeqList(L, 3);
    printSeqList(L);
    return 0;
}

测试结果

【吉大刘大有数据结构绿皮书】已知长度为n的线性表A采用顺序存储结构,写一算法,删除该线性表中所有值为item的数据元素。_第5张图片

你可能感兴趣的:(算法,数据结构,排序算法)