本节代码主要来自王道单科18页的综合应用题。
一、18页第1题。从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。
空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行 。
核心代码:
bool DeleteMinElem(Sqlist &L,ElemType &value){ // 18页第1题。从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。 //空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行 if(L.length==0){ printf("顺序表为空"); return 0; } int pos=0; value=L.data[0]; for(int i=1;i<L.length;i++){ if(L.data[i]<value){ value=L.data[i]; pos=i; } } L.data[pos]=L.data[L.length-1]; L.length--; return 1; }
二、18页第2题。设计一个高效的算法,将顺序表的所有元素逆置,要求算法的空间复杂度为O(1)
核心代码:
可以有两种方式:
第一种:定义两个循环指针i,j,其中i向后遍历,j向前遍历,这种更好记忆。
void Reverse(Sqlist &L){ int i,j; ElemType temp; for(i=0,j=L.length-1;i<j;i++,j--){ temp=L.data[i]; L.data[i]=L.data[j]; L.data[j]=temp; } }
第二种:j没有定义出来,用i和L.length(即L.length-i-1)的关系来表示其对称位置。
void Reverse2(Sqlist &L){ int i; ElemType temp; for(i=0;i<L.length/2;i++){ temp=L.data[i]; L.data[i]=L.data[L.length-i-1]; L.data[L.length-i-1]=temp; } }
三、18页第3题。删除线性表中所有值为x的元素。要求时间复杂度O(n),空间复杂度O(1)。
核心代码:
可以有三种方式:
第一种:遍历时统计等于x的个数count,将不等于x的元素向前移动count个位置。
void DeleteElemX1(Sqlist &L,ElemType x){ int count=0;//计算元素等于x的个数 for(int i=0;i<L.length;i++){ if(L.data[i]==x) count++; else L.data[i-count]=L.data[i]; } L.length-=count; }
第二种:把不等于x的元素重新覆盖,个数为count。
此处count起到了统计不等于x的个数(即剩余元素的个数),也起到了覆盖元素时的遍历作用。
void DeleteElemX2(Sqlist &L,ElemType x){ int count=0;//这次是计算不等于x的个数 for(int i=0;i<L.length;i++){ if(L.data[i]!=x){ L.data[count]=L.data[i]; count++; //注意这一句要在后面,因为覆盖元素位置从0开始。 } } L.length=count; //这句不要忘了。 }
第三种:用头尾两个指针i,j从两端向中间移动,凡遇到左端值x的元素时,直接将最右端值非x的元素左移至值为x的数据元素位置,直到两指针相遇。
但这种方法会改变原表元素的相对位置。不推荐。就暂时不写了。
以下是以上三道题的全部测试代码(可直接运行):
#include<stdio.h> #define true 1 #define false 0 #define MaxSize 100 #define ElemType int #define Status int typedef struct{ ElemType data[MaxSize]; int length; }Sqlist; //构造一个空的线性表L void InitList(Sqlist &L){ L.length=0; } bool ListInsert(Sqlist &L,int i,ElemType e){ //将元素e插到顺序表L中第i个位置 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; } void ListLoad(Sqlist L){ if(L.length==0){ printf("当前顺序表为空\n"); return; } printf("当前顺序表元素为:"); for(int i=0;i<L.length;i++) printf("%d ",L.data[i]); printf("\n"); return; } // 18页第1题。从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值。 //空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行 bool DeleteMinElem(Sqlist &L,ElemType &value){ if(L.length==0){ printf("顺序表为空"); return 0; } int pos=0; value=L.data[0]; for(int i=1;i<L.length;i++){ if(L.data[i]<value){ value=L.data[i]; pos=i; } } L.data[pos]=L.data[L.length-1]; L.length--; return 1; } void Reverse1(Sqlist &L){ //18页第2题。设计一个高效的算法,将顺序表的所有元素逆置,要求算法的空间复杂度为O(1) int i,j; ElemType temp; for(i=0,j=L.length-1;i<j;i++,j--){ temp=L.data[i]; L.data[i]=L.data[j]; L.data[j]=temp; } } void Reverse2(Sqlist &L){ //18页第2题。设计一个高效的算法,将顺序表的所有元素逆置,要求算法的空间复杂度为O(1) int i; ElemType temp; for(i=0;i<L.length/2;i++){ temp=L.data[i]; L.data[i]=L.data[L.length-i-1]; L.data[L.length-i-1]=temp; } } //遍历时统计等于x的个数count,将不等于x的元素向前移动count个位置。 void DeleteElemX1(Sqlist &L,ElemType x){ int count=0;//计算元素等于x的个数 for(int i=0;i<L.length;i++){ if(L.data[i]==x) count++; else L.data[i-count]=L.data[i]; } L.length-=count; } //把不等于x的元素重新覆盖,个数为count。 //此处count起到了统计不等于x的个数(即剩余元素的个数),也起到了覆盖元素时的遍历作用。 void DeleteElemX2(Sqlist &L,ElemType x){ int count=0;//这次是计算不等于x的个数 for(int i=0;i<L.length;i++){ if(L.data[i]!=x){ L.data[count]=L.data[i]; count++; //注意这一句要在后面,因为覆盖元素位置从0开始。 } } L.length=count; //这句不要忘了。 } int main(){ Sqlist T; ElemType min; ElemType e; int a; InitList(T); ListInsert(T,1,4); ListInsert(T,1,3); ListInsert(T,1,6); ListInsert(T,2,1); ListInsert(T,2,8); ListInsert(T,2,8); ListInsert(T,2,9); ListLoad(T); while(1){ printf("1:删除最小元素\n"); //DeleteMinElem printf("2:所有元素逆置(方法1)\n"); //Reverse1 printf("3:所有元素逆置(方法2)\n"); //Reverse2 printf("4:删除值等于x的所有元素(方法1)\n"); //DeleteElemX1 printf("5:删除值等于x的所有元素(方法2)\n"); //DeleteElemX2 printf("请选择:"); scanf("%d",&a); switch(a){ case 1:if(DeleteMinElem(T,min)) printf("成功删除最小元素%d\n",min); else printf("删除失败\n"); break; case 2:Reverse1(T); break; case 3:Reverse2(T); break; case 4:scanf("%d",&e); DeleteElemX1(T,e); break; case 5:scanf("%d",&e); DeleteElemX2(T,e); break; default:return 1; } ListLoad(T); } }
删除最小元素:
顺序表逆置:
删除值等于x的所有元素: