Rocket学代码——C++版数据结构——顺序表篇(持续更新)

  1. 顺序表

线性结构(线性表):一维数组,队列,栈

先整理一维数组的题,以及代码实现,如下:

首先我们需要建立顺序表的结构,以及初始化和创建一维数组

分别是:初始化顺序表;销毁顺序表(自动调用);创建一个顺序表;打印顺序表

#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;
}

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值