-
顺序表
线性结构(线性表):一维数组,队列,栈
先整理一维数组的题,以及代码实现,如下:
首先我们需要建立顺序表的结构,以及初始化和创建一维数组
分别是:初始化顺序表;销毁顺序表(自动调用);创建一个顺序表;打印顺序表
#include "stdafx.h"
#include <iostream>
using namespace std;
#define MAXSIZE 3
#define Node ElemType
#define ERROR 0
typedef int DateType;
class Node {//创建一个节点类
public:
DateType data;
};
class SqList {//创建一个顺序表的类
public:
SqList();//功能1:初始化顺序表
~SqList();//功能2:销毁顺序表
void CreateSqList(int n);//功能3:定义创建一个顺序表
void Print();//功能4:打印顺序表
private:
Node * elem;//顺序表的基址
int length;//顺序表的长度
};
//功能1
SqList::SqList() {
elem = new ElemType[MAXSIZE];//开辟空间
if (!elem)//当溢出时候报异常
exit(OVERFLOW);
length = 0;
}
//功能2
SqList::~SqList() {
delete[] elem;//删除基址的指针
}
//功能3
void SqList::CreateSqList(int n) {
if (n < 0) {
cout << "input number of node is error!" << endl;
exit(EXIT_FAILURE);
}
else {
int i;
for (i = 0; i < n; i++) {//循环向数组中添加元素
cout << "Please input the key of NO." << i + 1 << " : ";
cin >> elem[i].data;
}
length = n;//更改顺序表的长度
}
}
//功能4
void SqList::Print() {
if (length > 0) {
for (int i = 0; i < length; ++i)
cout << elem[i].data << " ";
cout << endl;
}
else
cout << "The SqList is empty" << endl;
//主函数(功能函数需要在这里调用)
int main()
{
//创建一个顺序表,并且打印
SqList l;
int n;
cout << "please input number: ";
cin >> n;
l.CreateSqList(n);
l.Print();
system("pause");
return 0;
}
功能5:删除最小值,输出最小值(假设min是唯一的)
思路:
用一个value值来传递要删除的最小值,设置一个pos值来记录最小值的地址
首先要找到最小值,一维数组的第一个值假设为最小值(elem[0],data)
然后数组中的下一个值与当前最小值做对比(value),如果比value小就替换
依次循环,得到最终最小值,因为函数用&value做实参,改变的是主函数中value,这样便可以传递被删除的最小值
最后用数组最后一个元素来填补删除的坑,数组长度减1
注意,因为函数是bool形的,删除成功返回的是true值,主函数需要一个bool值来接收。
class SqList {//创建一个顺序表的类
public:
//......
bool Del_Min(SqList &L, int &value);//功能五:删除最小值,输出最小值(假设min是唯一的)
private:
Node * elem;//顺序表的基址
int length;//顺序表的长度
};
//功能5
bool SqList::Del_Min(SqList &L, int &value) {
if (L.length==0)
return false;
value = L.elem[0].data;
int pos = 0;//用于标记最小值
for (int i = 1; i < L.length; i++) {//往后每一位依次和做对比,小的做替换
if (L.elem[i].data < value) {
value = L.elem[i].data;
pos = i;
}
}
L.elem[pos].data = L.elem[L.length - 1].data;//最后一个值来填补最小值的坑
L.length--;//长度缩减
return true;
}
int main()
{
//......
//删除最小值,输出最小值,并且打印顺序表
int value = 0;//用于传递最小值
bool key;
key=l.Del_Min(l, value);
if (key = true)
cout << "the Min_key is : "<<value;
else
cout << "Can`t find the Min_key";
cout << endl;
l.Print();
//......
}
功能6:编写时间复杂度为O(n),空间复杂度为O(1)的算法,删除线性表中的所有值为x的元素
思路:
因为空间复杂度为O(1),只能设定一个k用于记录不等于x的个数,来刷新一维数组,初始k=0
用一个循环,如果不等于x的值,就将这个元素添加进elem[k],k++
最后把一维数组的长度修改为k,则完成所有x值的删除
class SqList {//创建一个顺序表的类
public:
void Del_all_x(SqList &L, int x);//功能6:删除所有值为x的元素
private:
Node * elem;//顺序表的基址
int length;//顺序表的长度
};
//功能6
void SqList::Del_all_x(SqList &L, int x) {
int k = 0;//用于记录删除后剩余顺序表元素的个数
for (int i = 0; i < L.length; i++) {
if (L.elem[i].data != x) {
L.elem[k].data = L.elem[i].data;
k++;
}
}
L.length = k;
}
int main()
{
//......
//删除所有值为x的元素
int x_del;
cout << "input the x_del: ";
cin >> x_del;
l.Del_all_x(l,x_del);
l.Print();
system("pause");
return 0;
}
或者用另一个思路:
也设定一个k值,只不过是记录等于x值的元素个数
然后用一个while循环,遍历整个一维数组,如果等于x,k就增加(k++),i++
否则,就把不等于x值添加到 [i-k] 的地址去,i++
最后一维数组的长度修改为 length-k
//功能6
void SqList::Del_all_x(SqList &L, int x) {
int k = 0,i=0;//用于记录删除后剩余顺序表元素的个数
while (i < L.length) {
if (L.elem[i].data == x)
k++;
else
L.elem[i - k].data == L.elem[i].data;
i++;
}
L.length = L.length-k;
}
功能7:要求空间复杂度为O(1),实现所有的元素就地逆置
思路:
因为不能用辅助数组,所以就用折半的方法
//功能7
void SqList::Reverse(SqList &L) {
int temp;
for (int i = 0; i < L.length / 2; i++) {
temp = L.elem[i].data;
L.elem[i].data = L.elem[L.length - i - 1].data;
L.elem[L.length - i - 1].data = temp;
}
}
功能8:前提顺序表有序,删除s与t之间的所有元素,包含s,t,且是s<t。如果s,t不合理,或者顺序表为空,则显示出错信息并推出运行
思路:
因为如果输入信息有错,则报错推出运行,所以考虑用bool型
先用一个for循环找到第一个大于等于s的元素,然后用第二个for循环找到大于t的第一个元素,用后者填补前者,
然后再用一个循环继续往下找,i++,j++
最后当<L.length的时候终止,L.length等于 i 的值。
//功能8:删除s与t之间的所有元素
bool SqList::Del_s_t(SqList &L, int s, int t) {
int i, j;
if (s >= t || L.length == 0)
return false;
for (i = 0; i < L.length&&L.elem[i].data < s; i++);//寻找第一个>=s的元素
if (i >= L.length)
return false;
for (j = i; j < L.length&&L.elem[j].data <= t; j++);//寻找第一个>t的元素
for (; j < L.length; i++, j++)//继续往下,向前填补
L.elem[i].data = L.elem[j].data;
L.length = i;//删除后的长度
return true;
}
另外一个思路:
只用一个循环,如果是在s-t范围内的元素,设定一个k值,进行++,
否则,将第i值前移到i-k的位置
最后length减去k的值
//功能8:删除s与t之间的所有元素
bool SqList::Del_s_t(SqList &L, int s, int t) {
int i, k=0;//k用于记录在s-t范围内的元素个数
if (s >= t || L.length == 0)
return false;
for (i = 0; i < L.length; i++) {
if (L.elem[i].data >= s && L.elem[i].data <= t)
k++;
else
L.elem[i - k].data = L.elem[i].data;
}
L.length -= k;
return true;
}
@功能9:删除有序表中的值重复的多余元素,使得顺序表中的值均不相同
思路:设定i用于指向比较的元素,初始为0,j用于指向被比较的元素,初始为1
若相同,则j++;若不相同,并且将j所指的元素添加到i的位置,i++接着比较
最后length等于i+1
//功能9
bool SqList::Del_Same(SqList &L) {
if (L.length == 0)
return false;
int i, j;//i用于存储第一个被比较元素,j是工作指针
for (i = 0,j = 1; j < L.length; j++)
if (L.elem[i].data != L.elem[j].data)
L.elem[++i].data = L.elem[j].data;
L.length = i + 1;//i从0开始
}
功能9:将两个有序表合并为一个新的有序表,并返回新的顺序表
思路:
用一个SqList &C作为实参返回合并的新表,
首先,用一个while循环,判断顺序表A与B起始值的大小,小的先加入C,k++,对应的地址++
然后,q其中一个顺序表已经对比完毕,而还剩另一个,则将其全部加入到C的后端,k++
最后length等于k
//功能10
bool SqList::Merge(SqList A, SqList B, SqList &C) {
//if(A.length+B.length>C.MAXSIZE)
// return false; //y由于我们的SqList结构里没有MAXSIZE成员,所以先空着
int i = 0, j = 0, k = 0;
while (i < A.length&&j < B.length) {
if (A.elem[i].data < B.elem[j].data)
C.elem[k++].data = A.elem[i++].data;
else
C.elem[k++].data = B.elem[j++].data;
}
while(i<A.length)
C.elem[k++].data = A.elem[i++].data;
while(j<B.length)
C.elem[k++].data = B.elem[j++].data;
C.length = k;
return true;
}
int main()
{
//将两个有序表合并为一个新的有序表,并返回新的顺序表
SqList l;
int n;
cout << "please input number: ";
cin >> n;
l.CreateSqList(n);
l.Print();
SqList l2;
int n2;
cout << "please input number: ";
cin >> n2;
l2.CreateSqList(n2);
l2.Print();
SqList l3;
l3.Merge(l, l2, l3);
l3.Del_Same(l3);
l3.Print();
system("pause");
return 0;
}