五邑大学数据结构第二章作业大题部分答案及解析

五邑大学数据结构第二章作业答案及解析

前言

由于很多同学都反应这一个作业很难做,在我看来应该跟不会使用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可以找我。
有事没事多在班群里面讨论问题,技术都是讨论出来的

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值