1.从顺序表中删除除具有最小元素的元素(假设唯一)并由函数返回被删除元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。
算法思想:搜素整个顺序表,查找最小元素并记住其位置,搜素结束后用最后一个元素填补空出的原最小值元素的位置
bool Del_Min(SeqList *L,int &val)
{
if(0 == L->length)//用数组中的有效长度是否为0来判断数组是否为空
{
printf("数组为空!\n");
return false;
}
val = L->data[0];//用val存放数组第一个元素,然后与后序数组元素进行比较
int pos = 0;//用pos来记录最小元素的位置
for(int i = 1; i<L->length; ++i)
{
if(L->data[i]<val)
{
val = L->data[i];
pos = i;
}
}
L->data[pos] = L->data[L->length-1];
L->length--;//记得改变数组有效元素的个数
return true;
}
2.设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度1为O(1)
算法思想:扫描顺序表L的前半部分元素,对于元素L->data[i](0<=i<L->length/2),将其与后半部分的对应元素L->data[L->length-1-i]进行交换
void Reverse(SeqList*L)
{
int temp;//辅助变量
for(int i = 0; i < L->length/2; ++i)//在计算机中L->length/2应是向下取整
{
//通过中间变量改变数组元素的位置,因为仅借助一个变量temp,与问题规模无关,没有使用其他额外空间,所以空间复杂度O(1)
temp = L->data[i];
L->data[i] = L->data[L->length-1-i];
L->data[L->length-1-i] = temp;
}
return;
}
3.对长度为n的顺序表L,编写一个时间复杂度为O(n),空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素
方法1—算法细想:用k记录顺序表L中不等于x的元素个数(即需要保存的元素个数),扫描时将不等于x的元素移动到下标K的位置,并更新K值。扫描结束后修改L的长度
void Del_x_1(SeqList *L,int x)
{
int i, k = 0;
for(i = 0; i < L->length; ++i)
{
if(x != L->data[i])
{
L->data[k] = L->data[i];//将数组中的不等于x的元素重新放在数组中
++k;
}
}
L->length = k;
return;
}
规定数组的元素个数为10
方法2—算法思想:用K记录顺序表中等于X的元素个数,表扫描L边统计K,并将不等于X的元素前移K个位置。扫描结束后需修改L的长度
void Del_x_2(SeqList *L,int x)
{
int i = 0, k = 0;
while(i < L->length)
{
if(x == L->data[i])
{
++k;
}
else
L->data[i-k] = L->data[i];
++i;
}
L->length = L->length-k;//k是统计数组中等于x元素的个数
}
假设数组元素为1 2 9 2 3 4 5 6 7,x=2;删除数组所有为2的元素
i=0,k=0; 因为2!=1 所以L->data[0] = L->data[0] 数组元素为:1 2 9 2 3 4 5 6 7
i=1,k=0; 因为2==2 所以i = 2 数组元素为:1 2 9 2 3 4 5 6 7
i=2,k=1; 因为2!=9 所以L->data[1] = L->data[2] 数组元素为: 1 9 9 2 3 4 5 6 7
这是小编写的,复杂度为O(n^2),所以错误
void del_x_1(SeqList *L,int x)
{
int i = 0;
while(i < L->length)
{
if(L->data[i] == x)
{
for(int j = i; j < L->length; ++j)
{
L->data[j] = L->data[j+1];
L->length--;
}
}
else
++i;
}
4.从有序顺序表中删除其值在给定值s与t之间(要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示错误信息并退出运行
小编的算法思想是:用k记录所有在s与t之间的元素个数,然后用后面的元素将其代替
bool Del_st(SeqList *L)
{
int s,t;
printf("请输入s和t的值:\n");
scanf("%d%d",&s,&t);
if(s >= t || L->length == 0)
return false;
int i = 0,k = 0;
while(i < L->length)
{
if(L->data[i] > s && L->data[i] < t)
{
++k;
}
else
L->data[i-k] = L->data[i];
++i;
}
L->length = L->length-k;
return true;
}
王道书上的 将给定值也删除了,小编认为这是有问题的
王道书上算法思想:先寻找值大于或等于s的第一个元素(第一个删除的元素),然后寻找值大于t的第一个元素(最后一个删除的元素的下一个元素),要将这段元素也删除,只需要将后面的元素前移
bool Del_s_t2(SeqList *L,int s, int t)
{
int i,j;
if(s >= t || L->length == 0)
return false;
for(i = 0; i < L->length && L->data[i] < s; ++i);//找出值大于或等于s的第一个元素的位置
if(i >= L->length)
return false;
for(j = i; j < L->length && L->data[j] <= t;++j);//寻找值大于t的第一个元素的位置
for(; j < L->length;++i,++j)
L->data[i] = L->data[j];//前移,这时会将s到t(若数组中元素包括s和)此时s和t元素也会被覆盖
L->length = i;
return true;
}
第1~3题完整代码
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define InitSize 10
typedef struct Node
{
int *data;
int Maxsize,length;
}SeqList;
//函数说明
void InitList(SeqList *L);
bool Full(SeqList *L);
bool Append(SeqList *L,int x);
bool Del_Min(SeqList *L,int &val);
bool PrintList(SeqList *L);
bool Del_Min(SeqList *L,int &val);
void Reverse(SeqList*L);
//void del_x_1(SeqList *L,int x);
void Del_x_1(SeqList *L,int x);
void Del_x_2(SeqList *L,int x);
int main(void)
{
SeqList L;
InitList(&L);
Append(&L,4);
Append(&L,2);
Append(&L,8);
Append(&L,1);
Append(&L,6);
Append(&L,3);
Append(&L,18);
Append(&L,11);
Append(&L,-1);
Append(&L,0);
int val;
PrintList(&L);
/*Del_Min(&L,val);
printf("删除元素是:%d\n",val);
printf("数组剩余元素为:\n");
PrintList(&L);*/
/*Reverse(&L);
printf("逆序之后的元素为:\n");
PrintList(&L);*/
//del_x_1(&L,-1);
//Del_x_1(&L,11);
Del_x_2(&L,11);
printf("删除所有值为11的元素之后剩下元素为:\n");
PrintList(&L);
return 0;
}
//初始化
void InitList(SeqList *L)
{
L->data = (int *)malloc(sizeof(int)*InitSize);
if(NULL == L->data)
{
printf("动态内存分配失败!\n");
exit(-1);
}
L->Maxsize = InitSize;
L->length = 0;
return;
}
//判断数组是否满
bool Full(SeqList *L)
{
if(L->Maxsize == L->length)
return true;
else
return false;
}
//增加数组元素
bool Append(SeqList *L,int x)
{
if(Full(L))
return false;
L->data[L->length] = x;
L->length++;
return true;
}
//遍历输出
bool PrintList(SeqList *L)
{
if(0 == L->length)
return false;
for(int i = 0; i < L->length; ++i)
{
printf("%d\n",L->data[i]);
}
return true;
}
//王道书--第二章--应用题--第一题
//算法思想:搜素整个顺序表,查找最小元素并记住其位置,搜素结束后用最后一个元素填补空出的原最小值元素的位置
bool Del_Min(SeqList *L,int &val)
{
if(0 == L->length)
{
printf("数组为空!\n");
return false;
}
val = L->data[0];
int pos = 0;
for(int i = 1; i<L->length; ++i)
{
if(L->data[i]<val)
{
val = L->data[i];
pos = i;
}
}
L->data[pos] = L->data[L->length-1];
L->length--;
return true;
}
//王道书--第二章--应用题--第二题
//算法思想:扫描顺序表L的前半部分元素,对于元素L->data[i](0<=i<L->length/2),将其与后半部分的对应元素L->data[L->length-1-i]进行交换
void Reverse(SeqList*L)
{
int temp;//辅助变量
for(int i = 0; i < L->length/2; ++i)//在计算机中L->length/2应是向下取整
{
temp = L->data[i];
L->data[i] = L->data[L->length-1-i];
L->data[L->length-1-i] = temp;
}
return;
}
//王道书--第二章--应用题--第三题
//自己的算法时间复杂度应该为O(n^2),不符合题意
/*void del_x_1(SeqList *L,int x)
{
int i = 0;
while(i < L->length)
{
if(L->data[i] == x)
{
for(int j = i; j < L->length; ++j)
{
L->data[j] = L->data[j+1];
L->length--;
}
}
else
++i;
}
}*/
//解法1:用k记录顺序表L中不等于x的元素个数(即需要保存的元素个数),扫描时将不等于x的元素移动到下标K的位置,并更新K值。扫描结束后修改L的长度
void Del_x_1(SeqList *L,int x)
{
int i, k = 0;
for(i = 0; i < L->length; ++i)
{
if(x != L->data[i])
{
L->data[k] = L->data[i];
++k;
}
}
L->length = k;
return;
}
//解法2:用K记录顺序表中等于X的元素个数,表扫描L边统计K,并将不等于X的元素前移K个位置。扫描结束后需修改L的长度
void Del_x_2(SeqList *L,int x)
{
int i = 0, k = 0;
while(i < L->length)
{
if(x == L->data[i])
{
++k;
}
else
L->data[i-k] = L->data[i];
++i;
}
L->length = L->length-k;
}
第4题完整代码
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define InitSize 10
typedef struct Node
{
int *data;
int Maxsize,length;
}SeqList;
//函数说明
void InitList(SeqList *L);
bool Full(SeqList *L);
bool Append(SeqList *L,int x);
bool PrintList(SeqList *L);
bool Del_st(SeqList *L);
bool Del_s_t2(SeqList *L,int s, int t);
int main(void)
{
SeqList L;
InitList(&L);
Append(&L,1);
Append(&L,2);
Append(&L,3);
Append(&L,4);
Append(&L,5);
Append(&L,6);
Append(&L,7);
Append(&L,8);
Append(&L,9);
Append(&L,10);
printf("增加元素之后数组的值为:\n");
PrintList(&L);
//Del_st(&L);
//PrintList(&L);
Del_s_t2(&L,2,6);
printf("删除元素之后数组元素为:\n");
PrintList(&L);
return 0;
}
//初始化
void InitList(SeqList *L)
{
L->data = (int *)malloc(sizeof(int)*InitSize);
if(NULL == L->data)
{
printf("动态内存分配失败!\n");
exit(-1);
}
L->Maxsize = InitSize;
L->length = 0;
return;
}
//判断数组是否满
bool Full(SeqList *L)
{
if(L->Maxsize == L->length)
return true;
else
return false;
}
//增加数组元素
bool Append(SeqList *L,int x)
{
if(Full(L))
return false;
L->data[L->length] = x;
L->length++;
return true;
}
//遍历输出
bool PrintList(SeqList *L)
{
if(0 == L->length)
return false;
for(int i = 0; i < L->length; ++i)
{
printf("%d\n",L->data[i]);
}
return true;
}
bool Del_st(SeqList *L)
{
int s,t;
printf("请输入s和t的值:\n");
scanf("%d%d",&s,&t);
if(s >= t || L->length == 0)
return false;
int i = 0,k = 0;
while(i < L->length)
{
if(L->data[i] > s && L->data[i] < t)
{
++k;
}
else
L->data[i-k] = L->data[i];
++i;
}
L->length = L->length-k;
return true;
}
bool Del_s_t2(SeqList *L,int s, int t)
{
int i,j;
if(s >= t || L->length == 0)
return false;
for(i = 0; i < L->length && L->data[i] < s; ++i);
if(i >= L->length)
return false;
for(j = i; j < L->length && L->data[j] <= t;++j);
for(; j < L->length;++i,++j)
L->data[i] = L->data[j];
L->length = i;
return true;
}