问题:已知长度为n的线性表A采用顺序存储结构,请写一时间复杂度为O(n),空间复杂度为O(1)的算法,该算法删除线性表中所有值为item的数据元素。(O(1)表示算法是辅助空间为常数)
解题过程:这问题不难,很快可以写出算法:
void Delete(SqList *L, int item)
{
int i,j=0;
for(i=0;i<L->length;i++)
if(L->elem[i]!=item)
L->elem[j++]=L->elem[i];
L->length=j;
}
但书上给出的解法为:
void Delete(SqList *L, int item)
{
int i=0;
int j=L->length-1; //设立数组头尾指针
while(i<j)
{
while(i<j&&L->elem[i]!=item)
i++; //若值不为item,头指针右移
while(i<j&&L->elem[j]==item)
j--; //若值为item,尾指针左移
if(i<j)
L->elem[i++]=L->elem[j--];
}
L->length=j+1;
}
乍一看,并没有看懂(算法似乎很复杂),认真重看一遍,终于搞懂了,不禁一阵狂喜,简单的问题被他搞得这么复杂(三个while循环)。但再仔细想想,其实是两种不同的思路:第一种是将表中不等于item的元素复制到原表中,覆盖原来的数据元素;第二种是从前往后寻找第一个为item的元素,用最后不为item的元素覆盖它。就本题而言,第一种方法应该更简单一些,但第二种不失是一个思路,比如下面这一问题
问题:顺序存储的线性表A,其数据元素为整型,试编写一算法,将A拆成B、C和D三个表,使得A中的负数放入B,零放入C,正数放入D,要求B、C、D不另外设置而利用A的空间。
程序:
#include<stdio.h>
#include<malloc.h>
#define ListSize 50
typedef struct
{
int *elem;
int length;
int listsize;
} SqList;
void Initiate(SqList *L)
{
L->elem=(int *)malloc(ListSize*sizeof(int));
L->length=0;
L->listsize=ListSize;
}
void Divide(SqList *A, SqList *B, SqList *C, SqList *D)
{
int i=0;
int j=A->length-1; //设立数组头尾指针
int k=0,m;
while(i<j)
{
while(i<j&&A->elem[i]<0)
i++; //若值为负数,头指针右移
while(i<j&&A->elem[j]>0)
j--; //若值为正数,尾指针左移
if(i<j&&A->elem[i]!=0)
{
m=A->elem[i];
A->elem[i]=A->elem[j];
A->elem[j--]=m;
}
else if(i<j&&A->elem[i]==0)
{
k=i+1;
while(k<j&&A->elem[k]==0)
k++; //寻找elem[i]后第一个不为零的元素下标
m=A->elem[i];
A->elem[i]=A->elem[k];
A->elem[k]=m;
if(k==j)
break;
}
}
if(i==0) //如果有负数,放入B
B->length=0;
else if(j==A->length-1)
{
B->elem=&A->elem[0];
B->length=i+1;
}
else
{
B->elem=&A->elem[0];
B->length=i;
}
if(k==0) //如果有零,放入C
C->length=0;
else
{
C->elem=&A->elem[i];
C->length=k-i+1;
}
if(j==A->length-1) //如果有正数,放入D
D->length=0;
else if(i==0)
{
D->elem=&A->elem[j];
D->length=A->length-j;
}
else
{
D->elem=&A->elem[j+1];
D->length=A->length-j-1;
}
}
void main()
{
int i,item;
SqList AList,BList,CList,DList;
Initiate(&AList);
for(i=0;i<10;i++)
scanf("%d",&AList.elem[i]);
AList.length=10;
for(i=0;i<AList.length;i++)
printf("elem[%d]=%d/n",i,AList.elem[i]);
item=5;
Divide(&AList,&BList,&CList,&DList);
for(i=0;i<AList.length;i++)
printf("A[%d]=%d/n",i,AList.elem[i]);
for(i=0;i<BList.length;i++)
printf("B[%d]=%d/n",i,BList.elem[i]);
for(i=0;i<CList.length;i++)
printf("C[%d]=%d/n",i,CList.elem[i]);
for(i=0;i<DList.length;i++)
printf("D[%d]=%d/n",i,DList.elem[i]);
}
运行结果:(从左到右依次是全为0、全为正、全为负和正常情况)
全部正确。