题目
已知长度为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):
其对应的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 <stdio.h>
#include<stdlib.h>
#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;
}