前言
由于很多同学都反应这一个作业很难做,在我看来应该跟不会使用C++语言创建模板并且测试方法。下面我将提供一些类方便同学们参考且使用
模板类
格式:
class mytest2 //类名
{
private:
/* data */ // 放各种私有数据
public: //放各种私有方法
mytest2(/* args */); // 有参构造
~mytest2(); // 无参构造
};
mytest2::mytest2(/* args */) // 在这里写私有方法(我们的作业写的位置就是这里)
{
}
mytest2::~mytest2()
{
}
顺序表
- 首先我们来看看顺序表(我将结合java来给大家讲讲这个模板怎么用)
- 该类对应了算法设计的第2题 与 第11题
#include <iostream>
using namespace std;
template <typename DataType>
class SeqList // 类名
{
private:
DataType data[10]; //私有,这里我给了定值,其实可以动态设置大小
int length;
public:
SeqList();
SeqList(DataType a[], int n);
int Length();
int Locate(DataType x);
void Insert(int i, DataType x); // 该方法用于插入元素(我比较懒所以没写)
DataType Delete(int i);
int Empty;
void del_all_x(int x); // 该方法对应了第二题
void delete2(int x,int y); // 该方法对应第十一题
void PrintList();
};
template <typename DataType>
SeqList<DataType>::SeqList(DataType a[], int n)
{
if (n > 10)
throw "参数非法";
{
for (int i = 0; i < n; i++)
{
data[i] = a[i];
}
length = n;
}
}
template <typename DataType>
void SeqList<DataType>::del_all_x(int x)
{
int i =0,j;
while(i<length&& data[i]!=x){ // 让 i 一直往后遍历,遇到data[i]==x时停下,这一步是为了找到第一个被删除元素前面的一个元素
i++;
}
for(j=i+1;j<length;j++){ // 从i+1处开始遍历表示 i为被删除数,j被删除数的下一个元素
if (data[j]!=x)
{
data[i++] = data[j]; // 这一步是为了让被删除元素被其下一个元素覆盖
}
}
length=i; // 直接把表的长度给切割了(删了多少就切多少)
}
template <typename DataType>
void SeqList<DataType>:: delete2(int x,int y){
cout<<"输入了:"<<x<<" 和 "<<y<<endl;
int i=0;
int n=0;
while(i<length){
if(data[i]>=x&&data[i]<=y){ // 如果在范围内
n++; //记录要删除的个数
}else {
data[i-n] = data[i]; // 如果不在范围内就将该数 覆盖前面被删除元素的位置上
}
i++;
}
length -=n; // 直接把表的长度给切割了(删了多少就切多少),换汤不换药
}
template <typename DataType>
void SeqList<DataType> :: PrintList()
{
for (int i = 0; i < length; i++)
{
cout<< data[i] << "\t";
}
cout<<endl;
}
int main()
{
int arr[10] = {1, 2, 2, 4, 5, 2, 7, 2, 9, 10};
SeqList<int> L(arr, 10); // 该方法是为了传入 长度跟数组 用于创建顺序表的
L.PrintList(); // 遍历给你看看初始表
//L.del_all_x(2); //调用该方法(完成第二题的效果)
//L.delete2(4,7); // 调用方法(完成第十一题的效果)
L.PrintList(); // 遍历给你看看效果
}
单链表
- 此处类的创建我是截取网上的代码,我加了一些私有方法方便我做测试
- 参考以下代码,对应第五题 第六题 第七题 第八题 第四题太简单了 我就不放上去了
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *next;
Node(int da = 0, Node *p = NULL) {
this->data = da;
this->next = p;
}
};
class List {
private:
Node *head, *tail;
int position;
public:
List() { head = tail = NULL; };
~List() {
delete head;
delete tail;
};
void print();
void Insert(int da = 0);
void Delete(int da = 0);
void Search(int da = 0);
void delArea(int mink,int maxk); // 第七题
void Min_Delete(); // 第五题
void deleteDuplicates(); // 第六题
int getValueAt(int position);
bool isSon(List l2); // 第八题
void setValueAt(int position, int da);
};
int List::getValueAt(int position) {
Node *p = head;
if (p == NULL) {
cout << "The List is Empty!" << endl;
} else {
int posi = 0;
while (p != NULL && posi != position) {
posi++;
p = p->next;
}
if (p == NULL) {
cout << "There is no value of this position in this List!" << endl;
} else {
cout << "In this Position,the value is" << p->data << endl;
}
}
return p->data;
}
void List::setValueAt(int position, int da) {
Node *p = head;
if (p == NULL) {
cout << "The List is Empty!" << endl;
} else {
int posi = 0;
while (p != NULL && posi != position) {
posi++;
p = p->next;
}
if (p == NULL) {
cout << "There is No Position in this List!" << endl;
} else {
p->data = da;
cout << "The Value in this position has been Updated!" << endl;
}
}
}
void List::Search(int da) {
Node *p = head;
if (p == NULL) {
cout << "Sorry, The List is Empty!" << endl;
return;
}
int count = 0;
while (p != NULL && p->data != da) {
p = p->next;
count++;
}
cout << "the value you want to search is at position %d" << count << endl;
}
void List::Delete(int da) {
Node *p = head, *q = head;
if (p == NULL) {
cout << "Sorry, The List is Empty!" << endl;
return;
}
while (p != NULL && p->data != da) {
q = p;
p = p->next;
}
q->next = p->next;
cout << "The Deletion Operation had been finished!" << endl;
}
void List::Insert(int da) {
if (head == NULL) {
head = tail = new Node(da);
head->next = NULL;
tail->next = NULL;
} else {
Node *p = new Node(da);
tail->next = p;
tail = p;
tail->next = NULL;
}
}
void List::delArea(int mink,int maxk){
cout<<"输入了:"<<mink<<"和"<<maxk<<endl;
Node *p = head; // 获取工作节点
Node *pre = p; // 获取一个头结点
Node *u; // 临时节点用于释放资源
while(p != NULL){
if(p->data<mink){
u = p;
head = p->next; // 我们让头结点直接连到p->next 这样前面的节点就断链,然后我们用 u临时节点保存 之后释放资源
}
if(p->data>maxk){
u = p;
pre->next = NULL; // 此处是为了直接把后面所有的元素都扔掉,这样就实现了断链,当然该方法我并没有写完(垃圾回收没写),因为作业没做完,我就先放在这了
break;
}
delete (u);
pre = p;
p=p->next;
}
}
bool List::isSon(List l2){
Node *p1 = head; // l1 的工作节点
Node *p2 = l2.head; // l2 的工作节点
Node *l2Head = p2; // l2 的头结点,用于返回
while(p1 != NULL){
if(p2->data==p1->data){ // 判断里面每一个值
p2 = p2->next;
}else {
p2 = l2Head; // 回到l2 头结点
}
p1 = p1->next;
if(p2 == NULL){ // 遍历完成,证明是子链
cout<<"我是子链"<<endl;
return true;
}
}
cout<<"我不是子链"<<endl;
return false;
}
void List::Min_Delete()
{ //head是带头结点的单链表的头指针,本算法按递增顺序输出单链表中的数据元素
Node *pre = head;
Node *p = pre->next;
Node *u;
while (head->next != NULL)
{ //循环到仅剩头结点
pre = head; //pre为元素最小值结点的前驱结点的指针
p = pre->next; //p为工作指针
while (p->next != NULL)
{
if (p->next->data < pre->next->data)
pre = p; //记住当前最小值结点的前驱
p = p->next;
}
cout << pre->next->data << endl;
u = pre->next;
pre->next = u->next;
delete (u);
}
delete (head); //释放头结点
}
void List:: deleteDuplicates()
{
Node *p = head, *q = NULL; //这里获取工作节点 p 还有一个临时节点 q
while(p != NULL) // 遍历p
{
q = p->next;
while(q != NULL && q->data == p->data)q = q->next; //因为题目讲了是有序的,当遇到相同节点的时候,我们让第一个有相同元素的元素 往后跳,让下一个相同元素断链就行了
p->next = q;
p = q;
}
}
void List::print() {
Node *p = head;
while (p != NULL) {
cout << p->data << " \a";
p = p->next;
}
cout << endl;
}
int main() {
List l1;
l1.Insert(1);
l1.Insert(1);
l1.Insert(2);
l1.Insert(3);
l1.Insert(3);
l1.Insert(5);
l1.Insert(6);
l1.print();
// l1.deleteDuplicates();
// l1.delArea(2,5);
// l1.print();
List l2;
l2.Insert(2);
l2.Insert(3);
l2.Insert(3);
l2.print();
bool flag = l1.isSon(l2);
cout << "The End!" << endl;
return 0;
}
双链表
- 这个我拿游泳圈的代码
- 对应第十题
- 这个写法更倾向于我们上学年的 C语言的写法,看个人习惯吧
老师所讲第十题的原理
- 同时拿头结点跟尾结点 一起向中间移动,每移动一次都判断头结点跟尾结点的值是否相同,当p!=q(这个是结点个数为奇数的时候),p->prior!=q(判断结点个数为偶数的时候)只要能来到这一步证明对称,来不到这一步证明就不对称
#include <iostream>
using namespace std;
typedef int ElemType;
typedef struct DNode{
ElemType data;
struct DNode *prior;
struct DNode *next;
}DLinkList;
//第十题
void CreateListR(DLinkList * &L,ElemType a[],int n){ //尾插法建立双链表
DLinkList *s , *r;
int i;
L=new DLinkList;
r = L;
for(i=0;i<n;i++){
s=new DLinkList;
s->data = a[i];
r->next = s;
s->prior=r;
r=s;
}
L->prior=s;
r->next=L;
}
bool IsEqual(DLinkList * &L){ // 该方法用于判断 环形链表是否对称
DLinkList *l , *r;
l=L->prior;
r=L->next;
// 该方法用了 两面夹击的方法,一个从头开始遍历,一个从尾开始遍历,当碰头如果没有遇到对称的部分就返回true
while(l!=r){
if(l->data!=r->data)
return false;
else{
l=l->prior;
r=r->next;
}
}
return true;
}
void Destroy(DLinkList *&L){
DLinkList *pre = L, *p = L->next;
while(p!=L){
delete(pre);
pre=p;
p=p->next;
}
delete(pre);
}
int main(){
DLinkList *L;
int n,i;
int a[10];
cout<<"请输入长度:"<<endl;
cin>>n;
for(i=0;i<n;i++){
cout<<"输入第"<<i+1<<"个值:";
cin>>a[i];
}
CreateListR(L,a,n);
if(IsEqual(L))
cout<<"双链表对称"<<endl;
else cout<<"双链表不对称"<<endl;
return 0;
}
后记
此博客用于便利同学们在做作业是遇到的不必要的困难,方便各位入门,感受老师的对我们深深的爱,内容是我赶忙加工出来的,如果有什么bug可以找我。
有事没事多在班群里面讨论问题,技术都是讨论出来的