线性表-顺序表、链表类模板的实现(数据结构基础 第2周)

学习完课程后,自己用C++实现了简单的顺序表和链表,并用约瑟夫问题做了测试,不保证完全正确。

其中有一点需要注意一下:C++中类模板声明头文件和实现头文件不可以分离到.h和.cpp中,否则无法正常编译,详见:https://www.zhihu.com/question/20630104

源码

1.顺序表

//seqlist.h

#pragma once
#include <iostream>
using namespace std;

template <class T> class seqlist
{
private:
    T* aList;  //存储顺序表的实例
    int maxSize;  //顺序表实例的最大长度
    int curLen;  //顺序表的当前长度
    int position;//当前处理位置
public:
    seqlist(const int size);
    ~seqlist();
    void clear();       //置空线性表
    int length();
    bool isEmpty();     //线性表为空时,返回true
    bool append(const T value);     //在表尾添加一个元素value,表的长度增1
    bool insert(const int p, const T value);    //在位置p上插入一个元素value,表的长度增1
    bool delet(const int p);        //删除位置p上的元素,表的长度减1
    bool getPos(int& p, const T value);     //查找值为value的元素并返回其位置
    bool getValue(const int p, T& value);   //把位置p元素值返回到变量value
    bool setValue(const int p, const T value);      //用value修改位置p的元素值
};

template <class T> seqlist<T>::seqlist(const int size)
{
    maxSize=size;
    aList = new T[maxSize];
    curLen=position=0;
}

template <class T> seqlist<T>::~seqlist()
{
    delete []aList;
}

template <class T> void seqlist<T>::clear()
{
    delete [] aList;
    curLen=position=0;
    aList=new T[maxSize];
}

template <class T> int seqlist<T>::length()
{
    return curLen;
}

template <class T> bool seqlist<T>::isEmpty()
{
    if (curLen==0) {
        return true;
    }
    else {
        return false;
    }
}

template <class T> bool seqlist<T>::append(const T value)
{
    if (curLen>=maxSize)  //检查顺序表是否溢出
    {
        cout << "The list is overflow" << endl;
        return false;
    }
    aList[curLen]=value;
    curLen++;
    return true;
}

//设元素类型为T,aList是存储顺序表的数组,maxSize是其最大长度;
//p为新元素value的插入位置,插入成功则返回true,否则返回false
template <class T> bool seqlist<T>::insert(const int p, const T value)
{
    if (curLen>=maxSize)  //检查顺序表是否溢出
    {
        cout << "The list is overflow" << endl;
        return false;
    }
    if (p<0 || p>curLen)  //检查插入位置是否合法
    {
        cout << "Insertion point is illegal" << endl;
        return false;
    }
    for(int i=curLen; i>p; i--)
        aList[i]=aList[i-1];   //从表尾curLen-1起往右移动直到p
    aList[p]=value;  //位置p处插入新元素
    curLen++;    //表的实际长度增1
    return true;
}

//设元素的类型为T;aList是存储顺序表的数组;p为即将删除元素的位置
//删除成功则返回true, 否则返回false
template <class T> bool seqlist<T>::delet(const int p)
{
    if (curLen<=0)  //检查顺序表是否为空
    {
        cout << "No element to delete" << endl;
        return false;
    }
    if (p<0 || p>curLen-1)  //检查删除位置是否合法
    {
        cout << "deletion is illegal" << endl;
        return false;
    }
    for(int i=p; i<curLen; i++)
        aList[i]=aList[i+1];
    curLen--;
    return true;
}

template <class T> bool seqlist<T>::getPos(int& p, const T value)
{
    for(int i=0; i<curLen; i++)
        if (aList[i]==value) {
            p=i;
            return true;
        }
        cout << "can not find element: " << value << endl;
        return false;
}

template <class T> bool seqlist<T>::getValue(const int p, T& value)
{
    if (curLen<=0)  //检查顺序表是否为空
    {
        cout << "No element" << endl;
        return false;
    }
    if (p<0 || p>curLen-1)  //检查删除位置是否合法
    {
        cout << "getvalue is illegal" << endl;
        return false;
    }
    value = aList[p];
    return true;
}

template <class T> bool seqlist<T>::setValue(const int p, const T value)
{
    if (curLen<=0)  //检查顺序表是否为空
    {
        cout << "No element" << endl;
        return false;
    }
    if (p<0 || p>curLen-1)  //检查删除位置是否合法
    {
        cout << "setvalue is illegal" << endl;
        return false;
    }
    aList[p] = value;
    return true;
}

//source.cpp

#include <iostream>
#include "seqlist.h"
#include <stdio.h>
using namespace std;

void josephus_seq(seqlist<int>& palist, int s, int m)
{
    int del = s;
    int w=0;
    for(int i=palist.length(); i>0; i--) {
        del=(del+m-1)%i;   //要删除的元素的索引
        if (del==0) del = i;
        palist.getValue(del-1, w);   //求出第del个元素的值
        printf("Out element %d \n", w);   //元素出列
        palist.delet(del-1);   //删除出列的元素
    }
}

int main() {
    seqlist<int> jos_alist(100);
    int n, s, m;
    printf("\n please input the values(<100) of n = ");  //参与游戏的人数
    scanf("%d", &n);
    printf("please input the values of s = ");   //开始的人
    scanf("%d", &s);
    printf("please input the values of m = ");   ///单词计数
    scanf("%d", &m);
    for (int i=0; i<n; i++) {
        jos_alist.append(i+1);
    }
    josephus_seq(jos_alist, s, m);
    return 0;
}

2.链表

//lnklist.h

#pragma once

template <class T>
class Link
{
public:
    T data;  //用于保存结点元素的内容
    Link<T> *next;  //指向后继结点的指针
    Link(const T info, Link<T>* nextValue=NULL) {
        data=info;
        next= nextValue;
    }
    Link():next(NULL) {}
};

template <class T>
class lnkList:public Link<T> {
private:
    Link<T> *head, *tail;      //单链表的头尾指针
    Link<T>* setPos(const int i);    //返回第i个元素的指针值
public:
    lnkList();   //构造函数
    ~lnkList();     //析构函数
    bool isEmpty();     //判断链表是否为空
    void clear();       //置空线性表
    int length();    //返回此链表当前实际长度
    bool append(const T value);     //在表尾添加一个元素value,表的长度增1
    bool insert(const int i, const T value);    //在位置i上插入一个元素value,表的长度增1
    bool delet(const int i);        //删除位置i上的元素,表的长度减1
    bool getValue(const int i, T& value);   //把位置i元素值返回到变量value
    bool getPos(int& i, const T value);     //查找值为value的元素并返回其位置
};

template <class T>
lnkList<T>::lnkList() {
    head=NULL;
    tail=NULL;
}

template <class T>
lnkList<T>::~lnkList() {
    if (head==NULL)
    {
        return;
    }
    Link<T>* cur=head;
    while(cur != NULL) {
        Link<T>* del=cur;
        cur = cur->next;
        delete del;
    }
    delete cur;
    head=NULL;
    tail=NULL;
}

template <class T>
Link<T>* lnkList<T>::setPos(const int i) {
    int count=0;
    Link<T>* p=head;  //循链定位,若i为0则定位到第一个结点
    while(p != NULL && count<i) {
        p=p->next;
        count++;
    }
    return p;   //指向结点i
}

template <class T>
bool lnkList<T>::insert(const int i, const T value) {
    Link<T> *p, *q;
    if ((p=setPos(i-1))==NULL)   //p是位置i结点的前驱
    {
        cout <<  "Insertion point is illegal" << endl;
        return false;
    }
    q = new Link<T>(value, p->next);
    p->next = q;
    if (p==tail)  //插入点在链尾,插入结点成为新的链尾
    {
        tail = q;
    }
    return true;
}

template <class T>
bool lnkList<T>::delet(const int i) {
    Link<T> *p, *q;
    if (i==0){  //删除头结点
        q=head;
        head=head->next;
        delete q;
        return true;
    }
    p=setPos(i-1);
    if (p==NULL || p==tail) {  //删除的结点不存在
        cout << "deletion is illegal" << endl;
        return false;
    }
    q=p->next;   //q是真正待删除结点
    if (q==tail)  //待删结点为尾结点,则修改尾指针
    {
        tail = p;
        p->next=NULL;
    }
    else
        p->next=q->next;   //删除结点q并修改链指针
    delete q;
    return true;
}

template <class T>
bool lnkList<T>::isEmpty() {
    if (head==NULL) {
        return true;
    }
    else {
        return false;
    }
}

template <class T>
void lnkList<T>::clear() {
    if (head==NULL)
    {
        return;
    }
    Link<T>* cur=head;
    while(cur != NULL) {
        Link<T>* del=cur;
        cur = cur->next;
        delete del;
    }
    delete cur;
    head=NULL;
    tail=NULL;
}

template <class T>
int lnkList<T>::length() {
    int count=0;
    Link<T>* cur=head;
    while(cur) {
        count++;
        cur = cur->next;
    }
    return count;
}

template <class T>
bool lnkList<T>::append(const T value) {
    Link<T>* newLink = new Link<T>(value);
    if (head==NULL) {
        head=newLink;
        tail=head;
    }
    else {
        tail->next = newLink;
        tail=newLink;
    }
    return true;
}

template <class T>
bool lnkList<T>::getPos(int& i, const T value) {
    Link<T>* cur=head;
    int count=0;
    while(cur) {
        if (cur->data==value)
        {
            i=count;
            return true;
        }
        cur = cur->next;
        count++;
    }
    cout << "can not find element: " << value << endl;
    return false;
}

template <class T>
bool lnkList<T>::getValue(const int i, T& value) {
    int count=0;
    Link<T>* cur=head;  //循链定位,若i为0则定位到第一个结点
    while(cur != NULL && count<i) {
        cur=cur->next;
        count++;
    }
    if (cur==NULL) {
        return false;
    }
    else {
        value = cur->data;
        return true;
    }
}

//source.cpp

#include <iostream>
#include "lnklist.h"
#include <stdio.h>
using namespace std;

void josephus_seq(lnkList<int>& palist, int s, int m)
{
    int del = s;
    int w=0;
    for(int i=palist.length(); i>0; i--) {
        del=(del+m-1)%i;   //要删除的元素的索引
        if (del==0) del = i;
        palist.getValue(del-1, w);   //求出第del个元素的值
        printf("Out element %d \n", w);   //元素出列
        palist.delet(del-1);   //删除出列的元素
    }
}

int main() {
    lnkList<int> jos_alist;
    int n, s, m;
    printf("\n please input the values(<100) of n = ");  //参与游戏的人数
    scanf("%d", &n);
    printf("please input the values of s = ");   //开始的人
    scanf("%d", &s);
    printf("please input the values of m = ");   ///单词计数
    scanf("%d", &m);
    for (int i=0; i<n; i++) {
        jos_alist.append(i+1);
    }
    josephus_seq(jos_alist, s, m);
    return 0;
}
时间: 2024-08-02 13:51:00

线性表-顺序表、链表类模板的实现(数据结构基础 第2周)的相关文章

线性表——顺序表与单链表学习小结

线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列. 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表.链表.栈.队列.字符串... 线性表在逻辑上是线性结构,也就说是连续的一条直线.但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储. 顺序表 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储.在数组上完成数据的增删查改. 链表 链表是一种物理存储结构上非连续.非顺序的存储结构,数据

java实现数据结构-线性表-顺序表,实现插入,查找,删除,合并功能

package 顺序表; import java.util.ArrayList; import java.util.Scanner; public class OrderList { /** * @param args * @author 刘雁冰 * @2015-1-31 21:00 */ /* * (以下所谓"位置"不是从0开始的数组下标表示法,而是从1开始的表示法.) * (如12,13,14,15,16数据中,位置2上的数据即是13) * * 利用JAVA实现数据结构-线性表-顺

C++数据结构与算法_1_线性表 --顺序表的实现与分析

顺序表的实现与分析 引 --线性表的抽象基类: template <typename T> class LinearList { public: LinearList(); ~LinearList(); virtual int Size() const = 0; //返回线性表所能够存储的最大长度 virtual int Length() const = 0; //当前线性表的长度 virtual int Search(T &x) const = 0; virtual int Loca

线性表&gt;&gt;顺序表---&gt;逆置所有元素

1 /*顺序表中所有的元素逆置 2 * 3 */ 4 #include <iostream.h> 5 using namespace std; 6 7 int main(){ 8 void reverse_arr(int arr[],int n); 9 int a[]={0,1,2,3,4,5,6,7}; 10 int n=7; 11 reverse_arr(a,n); 12 for(int i=0;i<=n;i++){ 13 cout << a[i] << &q

C++数据结构与算法_2_线性表 --顺序表的应用示例

h2.western { font-family: "Liberation Sans",sans-serif; font-size: 16pt; }h2.cjk { font-family: "微软雅黑"; font-size: 16pt; }h2.ctl { font-family: "AR PL UMing CN"; font-size: 16pt; }h1 { margin-bottom: 0.21cm; }h1.western { fon

线性表---顺序表&amp;链表

一.线性表 1.线性表中的元素是一对一的关系,除了第一个与最后一个元素之外其他数据元素都是首尾相连的. 如果是一对多就用树来表示,如果是多对多就用网状来表示. 2.线性表的两种存储结构 顺序表:用顺序结构保存数据,数据在内存中是连续的. 链表:用链式存储结构保存数据,数据在内存中是不连续的. 二.顺序表 1.顺序表: 顺序表一般使用数组实现,顺序表的相关操作与数组相关,一般都是移动数组元素 顺序表封装所需要的三个属性: 存储空间的起始位置.数组date的存储位置就是线性表存储空间的存储位置. 线

数据结构和算法-数据结构-线性结构-顺序表 链表和哈希表

####################################################### """ # 线性表是最基本的数据结构之一,在实际程序中应用非常广泛,它还经常被用作更复杂的数据结构的实现基础. # 根据线性表的实际存储方式,分为两种实现模型: # 顺序表, # 链表, # 下面分别进行研究, """ ####################################################### &qu

线性表顺序表模板 纯本人手工创造

/* ***********************************************Author        :mubaixuCreated Time  :2015-12-08 20:45:05File Name     :线性表顺序存储操作************************************************ */ 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <mal

数据结构之 线性表--顺序创建链表

数据结构实验之链表一:顺序建立链表 Time Limit: 1000MS Memory limit: 65536K 题目描述 输入N个整数,按照输入的顺序建立单链表存储,并遍历所建立的单链表,输出这些数据. 输入 第一行输入整数的个数N: 第二行依次输入每个整数. 输出 输出这组整数. 示例输入 8 12 56 4 6 55 15 33 62 示例输出 12 56 4 6 55 15 33 62 写的时候,定义一个结构体变量就要为它申请空间,不然程序会运行时出问题 ! #include <ios