HIT-哈工大数据结构-作业2(C++)

作业文件名LinkList.hSeqList.hStaticLinkList.h线性表.cpp
包含内容链式存储结构的类模板声明及函数实现顺序存储结构的类模板声明及函数实现静态链表存储结构的类模板声明及函数实现测试代码

1.实现线性表的顺序存储结构(SeqList)和链式存储结构(LinkList)。在上述 两种存储结构的基础上,分别实现以下算法:

顺序存储结构(SeqList)的类模板代码:

template<class Elementtype>
class SeqList {

public:
	SeqList(){//无参构造,初始化表长为0
		len = 0;
	}
	SeqList(Elementtype a[], int n);//有参构造,用一个数组初始化线性表
	//因为没有自己手动开辟空间,析构函数跟拷贝构造就用默认的。
	void Insert(int i, Elementtype x);//随机插入元素
	void Delete1(int i); //按位删除操作
	void Delete2(Elementtype x); //按值删除操作
	void Sort();//排序,我用的简单冒泡排序
	void DeleteRe();//对于已排好序的线性表,删除所有重复元素的算法。
	void Reverse();//线性表“逆置”算法
	void MoveRight(int k);//循环右移
	void MoveLeft(int k);//循环左移
	void Print();//打印线性表
	void MergeSeqList(SeqList& L);//合并两个已排好序线性表的算法
private:
	Elementtype elements[maxlength]; //数组,用来存放线性表中的元素
	int len;//记录表长
};

链式存储结构(LinkList)的类模板代码:

template<class Elementtype>
class LinkList
{
public:
    LinkList();//无参构造函数,生成具有头节点的空链表
    LinkList(Elementtype a[], int n);
    ~LinkList();//因为自己在堆中开辟了空间,所以得重新设置析构函数
    int Locate(Elementtype x);//查找
    void Insert(int i, Elementtype x);
    Elementtype Delete1(int i);//按位删除,返回被删除的值
    int Delete2(Elementtype x);//按值删除,返回该值的位置
    void Print();
    void Sort();//排序,我用的简单冒泡排序
    void DeleteRe();//对于已排好序的线性表,删除所有重复元素的算法。
    void Reverse();//线性表“逆置”算法
    void MoveRight(int k);//循环右移
    void MoveLeft(int k);//循环左移
    void MergeSeqList(LinkList& L);//合并两个已排好序线性表的算法
public:
    Node<Elementtype>* first;
};

① 删除给定元素的算法。

顺序存储结构(SeqList)的按位删除算法:

template <class Elementtype>
void SeqList<Elementtype>::Delete1(int i) //按位删除操作
{
	if (len == 0) {
		cout << "EMPTY!" << endl;
	}
	else if (i<1 || i>len) {
		cout << "WRONG!" << endl;
	}
	else {
		for (int j = i; j < len; j++)
			elements[j - 1] = elements[j];
		len--;
	}
}

顺序存储结构(SeqList)的按值删除算法:

template<class Elementtype>
struct Node
{
    Elementtype data;
    Node<Elementtype>* next;
};

template <class Elementtype>
void SeqList<Elementtype>::Delete2(Elementtype x) //按值删除操作,重复元素只删除第一个
{
	int p = 0;
	for (int i = 0; i < len; i++)
		if (elements[i] == x) {
			p = i + 1;
			break;
		}
	if (p == 0)
		cout << "未找到该值" << endl;
	else {
		for (int j = p; j < len; j++)
			elements[j - 1] = elements[j];
		len--;
	}
}

顺序存储结构(SeqList)的删除算法的测试代码及结果图:

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
SeqList<int> SL1(a, sizeof(a) / sizeof(int));
SL1.Print();
cout << "按位删除第五个元素" << endl;
SL1.Delete1(5);
SL1.Print();
cout << "按值删除5" << endl;
SL1.Delete2(5);
SL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LRTUznNz-1677332023085)(1.assets/G170KEQP_4T%KQY6A{0%BB3-16648924710912-16648924762094.png)]

链式存储结构(LinkList)的按位删除算法:

template<class Elementtype>
Elementtype LinkList<Elementtype>::Delete1(int i)//按位删除
{
    Node<Elementtype>* p = first;
    int count = 0;
    while (p != NULL && count < i - 1)
    {
        p = p->next;
        count++;
    }
    if (p == NULL || p->next == NULL) throw "位置为空!";//前驱为空或者前途是终端节点
    else {
        Node<Elementtype>* q = p->next;
        int x = q->data;
        p->next = q->next;
        return x;//返回被删除的值
    }
}

链式存储结构(LinkList)的按值删除算法:

template<class Elementtype>//只删除遇到的第一个值
int LinkList<Elementtype>::Delete2(Elementtype x)//按值删除
{
    int Y = Locate(x);
    Delete1(Y);
    return Y;
}

链式存储结构(LinkList)的删除算法的测试代码以及结果图:

我的有参构造用的头插法,所以顺序是反过来的。

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
LinkList<int> LL1(a, sizeof(a) / sizeof(int));
LL1.Print();
cout << "按位删除第五个元素" << endl;
LL1.Delete1(5);
LL1.Print();
cout << "按值删除5" << endl;
LL1.Delete2(5);
LL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zfdPZgt3-1677332023086)(1.assets/1.png)]

**② 对于已排好序的线性表,删除所有重复元素的算法。 **

顺序存储结构(SeqList)的删除重复元素算法:

template <class Elementtype>
void SeqList<Elementtype>::Sort() {//我用的简单冒泡排序
	int i, j;
	for (i = 0; i < len-1; i++)
	{
		bool flag = false;
		for (j = len-1; j >= i + 1; j--)
			if (elements[j] < elements[j - 1])
			{
				Elementtype temp = elements[j];
				elements[j] = elements[j - 1];
				elements[j - 1] = temp;
				flag = true;
			}
		if (flag == false)
			return;
	}
}

template <class Elementtype>
void SeqList<Elementtype>::DeleteRe()//对于已排好序的线性表,删除所有重复元素的算法。
{
	this->Sort();//内置了排序功能
	int i, j;
	for (i = 0; i < len - 1; i++) {
		Elementtype temp = elements[i];
		for (j = i + 1; j < len; j++) {
			if (elements[j] != temp)
				break;
			else
				Delete1(j + 1);
		}
	}
}

顺序存储结构(SeqList)的删除算法重复元素算法测试代码及结果:

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
SeqList<int> SL1(a, sizeof(a) / sizeof(int));
SL1.Print();
cout << "删除排序后的重复元素" << endl;
SL1.DeleteRe();
SL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UdlOmS8B-1677332023086)(1.assets/2.png)]

链式存储结构(LinkList)的删除重复元素算法:

template<class Elementtype>
void LinkList<Elementtype>::Sort()//这里用的选择排序
{
   
    for (Node<Elementtype>* p = first->next; p != NULL; p = p->next) {
        Node<Elementtype>* min = p;
        for (Node<Elementtype>* q = p->next; q != NULL; q = q->next) {
            if (q->data < min->data)
                min = q;
        }
        if (min != p) {//这里其实没有真正改变链表结构,只是交换了结构体的值
            Elementtype temp = min->data;
            min->data = p->data;
            p->data = temp;
        }
    }
}

template<class Elementtype>
void LinkList<Elementtype>::DeleteRe()//对于已排好序的线性表,删除所有重复元素的算法。
{
    this->Sort();//先排序
    int count = 1;//计数器
    for (Node<Elementtype>* p = first->next; p != NULL; p = p->next) {
        Elementtype temp = p->data;
        for (Node<Elementtype>* q = p->next; q != NULL; q = q->next) {
            int n = count + 1;
            if (q->data == temp)
                this->Delete1(n);
            n++;
        }
        count++;
    }
}

链式存储结构(LinkList)的删除重复元素算法测试代码及结果:

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
LinkList<int> LL1(a, sizeof(a) / sizeof(int));
LL1.Print();
cout << "删除排序后的重复元素" << endl;
LL1.DeleteRe();
LL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jqeAodAy-1677332023086)(1.assets/3.png)]

③ 线性表“逆置”算法。

顺序存储结构(SeqList)的逆置算法:

template <class Elementtype>
void SeqList<Elementtype>::Reverse()//线性表“逆置”算法
{

	int i = 0, j = len - 1;
	for (i = 0; i != j; i++) {

		Elementtype temp = elements[i];
		elements[i] = elements[j];
		elements[j] = temp;
		j--;
	}

}

顺序存储结构(SeqList)的逆置算法测试代码及结果:

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
SeqList<int> SL1(a, sizeof(a) / sizeof(int));
SL1.Print();
cout << "逆置算法" << endl;
SL1.Reverse();
SL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nQ51vJlc-1677332023086)(1.assets/4.png)]

链式存储结构(LinkList)的逆置算法:

template<class Elementtype>
void LinkList<Elementtype>::Reverse()//线性表“逆置”算法
{
    Node<Elementtype>* end;
    for (end = first->next; end->next != NULL; end = end->next);//找到末尾
    Node<Elementtype>* q = end;
    for (Node<Elementtype>* p = first->next; p != q; p = p->next) {
        Node<Elementtype>* T = q;
        Elementtype temp = p->data;
        p->data = q->data;
        q->data = temp;
        for ( q=first->next ; q->next != T; q = q->next);//找末尾的前驱          
    }
}

链式存储结构(LinkList)的逆置算法测试代码及结果:

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
LinkList<int> LL1(a, sizeof(a) / sizeof(int));
LL1.Print();
cout << "逆置算法" << endl;
LL1.Reverse();
LL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4wD5MIkX-1677332023087)(1.assets/5.png)]

**④ 线性表循环左移/右移 k 位的算法。 **

顺序存储结构(SeqList)的循环左移/右移k位算法:

template <class Elementtype>
void SeqList<Elementtype>::MoveRight(int k)//循环右移
{
	while (k--) {
		Elementtype temp = elements[len - 1];
		for (int i = len - 1; i > 0; i--) {
			elements[i] = elements[i - 1];
		}
		elements[0] = temp;
	}
}


template <class Elementtype>
void SeqList<Elementtype>::MoveLeft(int k)//循环左移
{
	while (k--) {
		Elementtype temp = elements[0];
		for (int i = 0; i < len - 1; i++) {
			elements[i] = elements[i + 1];
		}
		elements[len - 1] = temp;
	}

}

顺序存储结构(SeqList)的循环左移/右移k位算法测试代码及结果:

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
SeqList<int> SL1(a, sizeof(a) / sizeof(int));
SL1.Print();
cout << "右移两位" << endl;
SL1.MoveRight(2);
SL1.Print();
cout << "左移三位" << endl;
SL1.MoveLeft(3);
SL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-npyvFrB5-1677332023087)(1.assets/6.png)]

链式存储结构(LinkList)的循环左移/右移k位算法:

template<class Elementtype>
void LinkList<Elementtype>::MoveRight(int k)//循环右移
{
    while (k--)
    {
        Node<Elementtype>* end;
        for (end = first->next; end->next != NULL; end = end->next);//找到末尾
        Elementtype a = end->data;//用于临时保存末尾的数据
        Node<Elementtype>* q = end;
        while(q!=first->next) {
            Node<Elementtype>* T = q;//最开始指向末尾
            for (q = first->next; q->next != T; q = q->next);//把q变成T的前驱
            T->data = q->data;
        }
        first->next->data = a;
    }

}


template<class Elementtype>
void LinkList<Elementtype>::MoveLeft(int k)//循环左移
{
    while (k--) {
        Elementtype a = first->next->data;//用于临时保存第一个数据
        Node<Elementtype>* p;
        for ( p = first->next; p->next != NULL; p = p->next) {//循环出口为末尾
            p->data = p->next->data;          
        }
        p->data = a;
    }
}

链式存储结构(LinkList)的循环左移/右移k位算法测试代码及结果:

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
LinkList<int> LL1(a, sizeof(a) / sizeof(int));
LL1.Print();
cout << "右移两位" << endl;
LL1.MoveRight(2);
LL1.Print();
cout << "左移三位" << endl;
LL1.MoveLeft(3);
LL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-akCoHvsR-1677332023087)(1.assets/7.png)]

⑤ 合并两个已排好序的线性表的算法。

顺序存储结构(SeqList)的合并算法://这里的合并算法排序并删除了重复元素

template <class Elementtype>
void  SeqList<Elementtype>::MergeSeqList(SeqList& L) {
	int i = L.len;
	for (int j = 0; j < i; j++)
		this->Insert(1, L.elements[j]);
	this->DeleteRe();
	
}

顺序存储结构(SeqList)的合并算法测试代码及结果:

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
int b[] = { 654,12,56,546,12,645,32 };
SeqList<int> SL1(a, sizeof(a) / sizeof(int));
SeqList<int> SL2(b, sizeof(b) / sizeof(int));
SL1.Print();
SL2.Print();
cout << "合并算法" << endl;
SL1.MergeSeqList(SL2);
SL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8uWg5p4i-1677332023087)(1.assets/8.png)]

链式存储结构(LinkList)的合并算法://这里的合并算法未删除重复元素,所以二者结果有稍微不同。

template<class Elementtype>
void LinkList<Elementtype>::MergeSeqList(LinkList& L)//合并两个已排好序线性表的算法
{
    Node<Elementtype>* q ;
    for (q = L.first->next; q != NULL; q = q->next) {
        this->Insert(1, q->data);
    }
    this->Sort();
}

链式存储结构(LinkList)的合并算法测试代码及结果:

int a[] = { 1,999,87,87,7,5,5,7,9,10,31,541,521 };
int b[] = { 654,12,56,546,12,645,32 };
LinkList<int> LL1(a, sizeof(a) / sizeof(int));
LinkList<int> LL2(b, sizeof(b) / sizeof(int));
LL1.Print();
LL2.Print();
cout << "合并算法" << endl;
LL1.MergeSeqList(LL2);
LL1.Print();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QflWu4iN-1677332023087)(1.assets/9.png)]

设计线性表的静态单向链表存储结构,并实现线性表的“逆置”算法。

静态单向链表的类模板代码:

const int Maxsize = 100;

template<class DataType>
struct SNode {
    DataType data;
    int next;
};

template<class DataType>
class StaticLinkList {
public:
    StaticLinkList();//无参构造,初始化静态链表
    void BuildList(int L);//在静态链表空间中创建一个线性表实例,即把游标位置从可用空间表中移除
    int GetNode();//相当于NEW操作
    void FreeNode(int q);//回收操作
    void Insert(DataType x, int p);
    void Delete(int p);//参数为数组位置,删的实际是SList[p].next
    void Reverse(int L);//参数为游标头
    void print(int L);
    int FindEnd(int L);//查找一个游标指向线性表的末尾位置

public:
    SNode<DataType> SList[Maxsize];
    int av;//标识线性表
    int len;//记录线性表长度
};

初始化及在数组中创建以游标为标志的线性表:

template<class DataType>
StaticLinkList<DataType>::StaticLinkList() {//无参构造,初始化静态链表
    int j = 0;
    for (j = 0; j < Maxsize - 1; j++)
        SList[j].next = j + 1;
    SList[j].next = -1;//最后一个为空
    av = 0;//可用空间表
    len = 0;
}

template<class DataType>
void StaticLinkList<DataType>::BuildList(int L)//在静态链表空间中创建一个线性表实例,即把游标位置从可用空间表中移除
{
    int j = 0;
    for (j = 0; SList[j].next != L; j= SList[j].next);//已经到了空闲表中游标的前驱
    int i= SList[L].next;//空闲表中游标的后继
    SList[j].next = i;
    SList[L].next = -1;//初始化表头等于表尾

}

静态单向链表的逆置算法:

template<class DataType>
void StaticLinkList<DataType>::Reverse(int L) {
    int i = FindEnd(L);//L表的末尾
    int j ;
    for (j = SList[L].next; j != i; j = SList[j].next) {
        int temp = i;
        DataType n = SList[j].data;//i,j前后交换
        SList[j].data = SList[i].data;
        SList[i].data = n;
        for (i = j; SList[i].next != temp; i = SList[i].next);//找到i的前驱
    }
}

template<class DataType>
int StaticLinkList<DataType>::FindEnd(int L)//查找一个游标指向线性表的末尾位置
{
    int j;
    for (j = L; SList[j].next != -1; j = SList[j].next);//到达末尾
    return j;
}

静态单向链表的逆置算法的测试代码及结果:

int L = 2;//游标位置为2,相当于一个线性表实例
StaticLinkList<int> SLL;
SLL.BuildList(L);//以L为游标头在数组中创建一个线性表
for (int i = 1; i < 10; i++) //循环插入数据
	SLL.Insert(i, L);
cout << "逆置前" << endl;
SLL.print(L);//因为是头插法,所以插入顺序和表中数据是反过来的
cout << "逆置后" << endl;
SLL.Reverse(L);
SLL.print(L);
    SList[j].data = SList[i].data;
    SList[i].data = n;
    for (i = j; SList[i].next != temp; i = SList[i].next);//找到i的前驱
}

}

template
int StaticLinkList::FindEnd(int L)//查找一个游标指向线性表的末尾位置
{
int j;
for (j = L; SList[j].next != -1; j = SList[j].next);//到达末尾
return j;
}


静态单向链表的逆置算法的测试代码及结果:

```c++
int L = 2;//游标位置为2,相当于一个线性表实例
StaticLinkList<int> SLL;
SLL.BuildList(L);//以L为游标头在数组中创建一个线性表
for (int i = 1; i < 10; i++) //循环插入数据
	SLL.Insert(i, L);
cout << "逆置前" << endl;
SLL.print(L);//因为是头插法,所以插入顺序和表中数据是反过来的
cout << "逆置后" << endl;
SLL.Reverse(L);
SLL.print(L);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pL3hXeX4-1677332023088)(刘虹志作业2.assets/456.png)]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值