王道书第二章算法设计题

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;

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值