本习题来自王道考研教材,单独写算法不写代码跑一遍总感觉有缺憾,于是自己上手写了写试试。
1.从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删除的元素的值,空出的位置由最后一个元素填补,若顺序表为空则显示出错信息,并退出运行。
难度:简单
#include<iostream>
#include<stdlib.h>
#define maxSize 50
//以int数据为例实现一个顺序表
using namespace std;
typedef struct {
int* data;//存放元素的数组。
int length;//记录当前顺序表长度(元素个数)。
}sqlList;
bool deleteMin(sqlList &L,int &min)//利用引用的方式来返回删除的最小元素
{
//先判断是否为空
if (L.length == 0)
return false;
min = L.data[0];
int pos = 0;
for (int i = 1; i < L.length; i++)
{
if (L.data[i] < min)
{
min = L.data[i];
pos = i;
}
}
L.data[pos] = L.data[L.length - 1];
L.length--;
return true;
}
//测试程序
int main()
{
sqlList L;
L.data = new int[maxSize] {
78, 23, 1, 5, 3, 4};
L.length = 6;
printf("当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
int value = 0;
deleteMin(L,value);
printf("\n当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
printf("\n被删除元素为: %d", value);
}
运行结果:
***2.设计一个高效的算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)。***‘
难度:容易
思路:将两端元素交换位置。
#include<iostream>
#include<stdlib.h>
#define maxSize 50
//以int数据为例实现一个顺序表
using namespace std;
typedef struct {
int* data;//存放元素的数组。
int length;//记录当前顺序表长度(元素个数)。
}sqlList;
bool reverse(sqlList& L)
{
if (L.length == 0)
return false;
int temp = 0;
for (int i = 0; i <L.length/2; i++)
{
temp = L.data[i];
L.data[i] = L.data[L.length - 1 - i];
L.data[L.length - 1 - i] = temp;
}
printf("\n转置完成");
return true;
}
//测试程序
int main()
{
sqlList L;
L.data = new int[maxSize] {
78, 23, 1, 5, 3, 4};
L.length = 6;
printf("当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
int value = 0;
reverse(L);
printf("\n当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
}
3.对长度为n的顺序表L,编写一个时间复杂度O(n),空间复杂度O(1)
的算法,该算法删除线性表中所有值为x的元素。
难度:较容易
思路:若删除一个元素,则前面会少一个位置,删除x个元素,前面会空出x个位置,则从左往右遍历,用一个变量temp记录目前已经删除的元素个数,若次元素应该被删除,则temp+1,继续遍历,若此元素不应被删除,因为前面应该删除temp个元素,则将其向前移动temp位,遍历完成后再将顺序表长度减去temp.
#include<iostream>
#include<stdlib.h>
#define maxSize 50
//以int数据为例实现一个顺序表
using namespace std;
typedef struct {
int* data;//存放元素的数组。
int length;//记录当前顺序表长度(元素个数)。
}sqlList;
bool delete_all_x(sqlList& L, int x)
{
if (L.length == 0)
return false;
int temp = 0;
for (int i = 0; i < L.length; i++)
{
if (L.data[i] == x)
temp++;
else
L.data[i - temp] = L.data[i];
}
L.length -= temp;
cout <<endl<< "删除完成" << endl;
return true;
}
//测试程序
int main()
{
sqlList L;
L.data = new int[maxSize] {
78, 23, 1, 5, 1, 4,9};
L.length = 7;
printf("当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
int value = 0;
delete_all_x(L, 1);
printf("\n当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
}
运行结果:
4.从有序顺序表中删除其值在给定值s和t之间(s<t)的所有元素,如果s或t不合理或顺序表为空,则显示错误信息并退出运行。
难度:较为容易
思路:寻找大于等于s的第一个元素,和大于t的第一个元素,这之间的元素需要删除,也就是从大于t的第一个元素开始往前移动
#include<iostream>
#include<stdlib.h>
#define maxSize 50
//以int数据为例实现一个顺序表
using namespace std;
typedef struct {
int* data;//存放元素的数组。
int length;//记录当前顺序表长度(元素个数)。
}sqlList;
bool delete_in_range(sqlList& L, int s, int t)
{
if (L.length == 0 || s > t)
{
return false;
}
int i, j;
//寻找大于等于s的第一个元素
for (i = 0; i < L.length && L.data[i] < s; i++)
if (i > L.length) return false;//若此时不存在大于s的元素,return false
//寻找大于t的第一个元素
for (j = i; j < L.length && L.data[j] <= t; j++);
//从第j个元素(也就是大于t的第一个元素开始前移,同时移动指针i,j)
for (; j < L.length; i++, j++)
{
L.data[i] = L.data[j];
}
L.length = i;
return true;
}
//测试程序
int main()
{
sqlList L;
L.data = new int[maxSize] {
1,2,3,4,5,6};
L.length = 6;
printf("当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
int value = 0;
delete_in_range(L, 3, 5);
printf("\n当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
}
运行结果:
5.删除有序顺序表中所有重复的元素,使得表中所有元素的值均不同。
难度:较为容易
思路:用temp记录删除元素个数,用cur记录当前扫描的元素,参考之前边扫描边删除的思路。
//思路:边扫描边删除
bool delete_repeat(sqlList& L)
{
if (L.length == 0) return false;
int temp = 0;//用于记录当前删除的元素个数
int cur = L.data[0];//记录当前扫描到哪个元素
for (int i = 1; i < L.length; i++)
{
if (L.data[i] == cur) temp++;//如果遇到重复元素,则temp+1
else
{
//将cur换成当前元素,同时将cur向前移动temp位
cur = L.data[i];
L.data[i - temp] = L.data[i];
}
}
L.length -= temp;
cout << endl << "删除完毕" << endl;
}
//测试程序
int main()
{
sqlList L;
L.data = new int[maxSize] {
1,1,1,2,2,2,3,3,4,5,6,6,6};
L.length = 13;
printf("当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
delete_repeat(L);
printf("\n当前的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
}
运行结果:
6.将两个有序顺序表合并成为一个新的有序顺序表,并由函数返回结果顺序表
难度:容易
思路:用一个新的顺序表存储合并后的顺序表,用两个指针指向两个顺序表中的元素,从左向右扫描,两两比较。
bool merge(sqlList A, sqlList B, sqlList& C)
{
if (A.length + B.length > maxSize)
return false;
int i = 0, j = 0, k = 0;
while (i < A.length && j < B.length)
{
if (A.data[i] <= B.data[j])
{
C.data[k] = A.data[i];
i++; k++;
}
else {
C.data[k] = B.data[j];
j++; k++;
}
}
while (i < A.length)
{
C.data[k++] = A.data[i++];
}
while (j < B.length)
{
C.data[k++] = B.data[j++];
}
C.length = k;
return true;
}
//测试程序
int main()
{
sqlList L;
L.data = new int[maxSize] {
1,1,1,2,2,2,3,3,4,5,6,6,6};
L.length = 13;
sqlList l1;
l1.data = new int[maxSize] {
2, 3, 4, 5, 6};
sqlList l2;
l1.length = 5;
l2.data = new int[maxSize];
printf("\n L的顺序表元素为:");
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
printf("\n l1的顺序表元素为:");
for (int i = 0; i < l1.length; i++)
printf("%d ", l1.data[i]);
merge(L, l1, l2);
printf("\n l2的顺序表元素为:");
for (int j = 0; j < l2.length; j++)
{
printf(" %d", l2.data[j]);
}
}