第9章:群体类和群体数据的组织

本文展示了使用C++实现链表节点、链表类以及队列类的代码,包括插入、删除、遍历等基本操作。同时,还提供了排序功能的数组类,实现了插入排序、选择排序和冒泡排序算法。这些模板类可以用于处理不同类型的数据结构操作。
摘要由CSDN通过智能技术生成

第1关:实现链表结点

#include <iostream>
using namespace std;


template <class T>
class Node {
/********** Begin **********/
};
/**********  End  **********/

int main()
{
    int a[10];
    Node<int> n[10];
    // cout << "输入10 个整数:" << endl;
    for (int i = 0; i < 10; i ++) {
        cin >> a[i];
    }
    for (int i = 0; i < 9; i ++) {
        n[i].data = a[i];
        n[i].insertAfter(&n[i+1]);
    }
    n[9].data = a[9];
    Node<int>* np = &n[0];
    while (np != NULL) {
        cout << np->data << ' ';
        np = np->nextNode();
    }
    cout << endl;
    int f;
    // cout << "请输入要查找的数:";
    cin >> f;
    Node<int> p(0, &n[0]);
    np = &p;
    while (np->nextNode() != NULL) {
        while (np->nextNode() != NULL && np->nextNode()->data == f)
            np->deleteAfter();
        if(np->nextNode() != NULL)
            np = np->nextNode();
    }
    // cout << "删除后的链表:" << endl;
    np = p.nextNode();
    while (np != NULL) {
        cout << np->data << ' ';
        np = np->nextNode();
    }
    np = &p;
    while (np->nextNode() != NULL)
        np->deleteAfter();
    cout << endl;
    return 0;
}

第2关:实现链表

#include <iostream>
template <class T>
class Node {
private:
    T data;
public:
    Node* next;
    Node();
    Node(const T& data, Node<T>* nt = 0);
//  Node(T data, Node<T>* n = NULL);
    T& getData();
};

template <class T>
Node<T>::Node() {
    data = 0;
    next = NULL;
}

template <class T>
Node<T>::Node(const T& d, Node<T>* nt) {
    data = d;
    next = nt;
}

template <class T>
T& Node<T>::getData() {
    return data;
}

/********** Begin **********/

template <class T>
class LinkedList {
private:
    Node<T> *front, *rear; //表头和表尾指针
    Node<T> *prevPtr, *currPtr; //记录表当前遍历位置的指针,由插入和删除操作更新
    int size; //表中元素个数
    int position; //当前元素在表中的位置序号。由函数reset使用

    Node<T>* newNode(const T& item, Node<T> *ptrNext = NULL); //生成新节点,数据与为item,指针域为prtNext
    void freeNode(Node<T> *p); //释放节点

    void copy(const LinkedList<T>& L); //将链表L复制到当前表(假设当前表为空),被复制构造函数和operator=调用

public:
    LinkedList(); //构造函数
    LinkedList(const LinkedList<T>& L); //复制构造函数
    ~LinkedList(); //析构函数
    LinkedList<T>& operator = (const LinkedList<T>& L); //重载赋值运算符

    int getSize() const; //返回链表中元素个数
    bool isEmpty() const; //链表是否为空

    void reset(int pos = 0); //初始化游标的位置
    void next(); //使游标移动到下一个节点
    bool endOfList() const; //游标是否移动到链尾
    int currentPosition() const; //返回游标当前的位置
    
    void insertFront(const T& item); //在表头插入节点
    void insertRear(const T& item); //在表尾插入节点
    void insertAt(const T& item); //在当前节点之前插入节点
    void insertAfter(const T& item); //在当前节点之后插入节点

    T deleteFront(); //删除头节点
    void deleteCurrent(); //删除当前节点
    
    T& data(); //返回对当前节点成员数据的引用
    const T& data() const; //返回对当前节点成员数据的常引用

    void clear(); //清空链表:释放所有节点的内存空间,被析构函数和operator=使用
};

//生成新节点,数据与为item,指针域为prtNext
template <class T>
Node<T>* LinkedList<T>::newNode(const T& item, Node<T> *ptrNext) {
    Node<T> *n = new Node<T>(item, ptrNext);
    return n;
}

//释放节点
template <class T>
void LinkedList<T>::freeNode(Node<T> *p) {
    Node<T>* temp = front;
    while (temp->next != p) {
        temp = temp->next;
        if (temp == currPtr)
            position ++;
    }
    temp->next = p->next;
    if (currPtr == p)
        currPtr = currPtr->next;
    if (prevPtr == p) {
        prevPtr = prevPtr->next;
        currPtr = currPtr->next;
    }
    delete p;
    size --;
    position --;
}

//将链表L复制到当前表(假设当前表为空),被复制构造函数和operator=调用
template <class T>
void LinkedList<T>::copy(const LinkedList<T>& L) {
    Node<T> *temp = L.front, *ptr = front;
    while (temp != L.rear) {
        ptr->next = new Node<T>(temp->getData, NULL);
        ptr = ptr->next;
        temp = temp->next;
    }
    ptr->next = rear;
    size = L.getSize();
    position = L.currentPosition();
}

//构造函数
template <class T>
LinkedList<T>::LinkedList() {
    front = new Node<T>();
    rear = new Node<T>();
    front->next = rear;
    currPtr = rear;
    prevPtr = front;
    size = 0; //不计算front和rear
    position = 0; //在front下一个元素视为0
}

//复制构造函数
template <class T>
LinkedList<T>::LinkedList(const LinkedList<T>& L) {
    clear();
    copy(L);
}

//析构函数
template <class T>
LinkedList<T>::~LinkedList() {
    LinkedList::clear();
    delete front;
    delete rear;
}

//重载赋值运算符
template <class T>
LinkedList<T>& LinkedList<T>::operator = (const LinkedList<T>& L) {
    clear();
    copy(L);
}

//返回链表中元素个数
template <class T>
int LinkedList<T>::getSize() const {
    return size;
}

//链表是否为空
template <class T>
bool LinkedList<T>::isEmpty() const {
    return (size == 0);
}

//初始化游标的位置
template <class T>
void LinkedList<T>::reset(int pos) { //初始化游标位置
    if (pos > size) {
        // cout << "越界,无法访问" << endl;
        return;
    }
    int i = 0;
    prevPtr = front;
    currPtr = front->next;
    while (i < pos) {
        if (currPtr == rear) {
            // cout << "越界,无法访问" << endl;
            return;
        }
        i ++;
        currPtr = currPtr->next;
        prevPtr = prevPtr->next;
    }
    position = pos;
}

//使游标移动到下一个节点
template <class T>
void LinkedList<T>::next() {
    if (currPtr == rear) {
        // cout << "已经到达链表尾,无法移动" << endl;
        return;
    }
    currPtr = currPtr->next;
    prevPtr = prevPtr->next;
    position ++;
}


//游标是否移动到链尾
template <class T>
bool LinkedList<T>::endOfList() const {
    return (currPtr == rear);
}

//返回游标当前的位置
template <class T>
int LinkedList<T>::currentPosition() const {
    return position;
}

//在表头插入节点
template <class T>
void LinkedList<T>::insertFront(const T& item) {
    Node<T>* n = new Node<T>(item, front);
    front = n;
    size ++;
    position ++;
}

//在表尾插入节点
template <class T>
void LinkedList<T>::insertRear(const T& item) {
    Node<T>* temp = front;
    while (temp->next != rear)
        temp = temp->next;
    Node<T> *n = new Node<T>(item, rear);
    temp->next = n;
    size ++;
}

//在当前节点之前插入节点
template <class T>
void LinkedList<T>::insertAt(const T& item) {
    Node<T>* temp = new Node<T>(item, currPtr);
    prevPtr->next = temp;
    prevPtr = temp;
    size ++;
    position ++;
}

//在当前节点之后插入节点
template <class T>
void LinkedList<T>::insertAfter(const T& item) {
    Node<T>* temp = new Node<T>(item, NULL);
    temp->next = currPtr->next;
    currPtr->next = temp;
    size ++;
}

//删除头节点,实质是删除front->next
template <class T>
T LinkedList<T>::deleteFront() {
    if (front->next == rear) {
        // cout << "没有节点可以删除" << endl; 
    }
    if (prevPtr == front->next) {
        prevPtr = prevPtr->next;
        currPtr = currPtr->next;
    }
    Node<T>* temp = front->next;
    T d = temp->getData();
    front->next = temp->next;
    delete temp;
    size --;
    if (front->next != rear)
        position --;
    return d;
}

//删除当前节点
template <class T>
void LinkedList<T>::deleteCurrent() {
    Node<T>* temp = currPtr;
    currPtr = currPtr->next;
    delete temp;
    size --;
}
    
//返回对当前节点成员数据的引用
template <class T>
T& LinkedList<T>::data() {
    return currPtr->getData();
}

//返回对当前节点成员数据的常引用
template <class T>
const T& LinkedList<T>::data() const {
    return currPtr->getData();
}

//清空链表:释放所有节点的内存空间,被析构函数和operator=使用
template <class T>
void LinkedList<T>::clear() {
    Node<T>* temp;
    while (front->next != rear) {
        temp = front->next;
        front->next = temp->next;
        delete temp;
    }
    size = 0;
    position = 0;
}

/**********  Begin  **********/
template <class T>
class Queue : public LinkedList<T>{
    
};

/**********  End  **********/
using namespace std;

int main()
{
    LinkedList<int> A, B;
    int i, item;
    
    // cout << "请输入加入链表A的五个整数:";
    for (i = 0; i < 5; i ++) {
        cin >> item;
        A.insertRear(item);
    }
    // cout << "请输入加入链表B的五个整数:";
    for (i = 0; i < 5; i ++) {
        cin >> item;
        B.insertRear(item);
    }
    // cout << endl << "有序链表A中的元素为:";
    A.reset();
    while(!A.endOfList()) {
        cout << A.data() << " ";
        A.next();
    }
    cout << endl;
    // cout << endl << "有序链表B中的元素为:";
    B.reset();
    while(!B.endOfList()) {
        A.insertRear(B.data());
        cout << B.data() << " ";
        B.next();
    }
    cout << endl;
    
    // cout << endl << "加入链表B中元素后,链表A中的元素为:";
    A.reset();
    while(!A.endOfList()) {
        cout << A.data() << " ";
        A.next();    
    }
    cout << endl;
    return 0;
}

第3关:实现队列

#include <iostream>
template <class T>
class Node {
private:
    T data;
public:
    Node* next;
    Node();
    Node(const T& data, Node<T>* nt = 0);
//  Node(T data, Node<T>* n = NULL);
    T& getData();
};

template <class T>
Node<T>::Node() {
    data = 0;
    next = NULL;
}

template <class T>
Node<T>::Node(const T& d, Node<T>* nt) {
    data = d;
    next = nt;
}

template <class T>
T& Node<T>::getData() {
    return data;
}

/*
* 在LinkedList的设计中,采用了附加指针front和rear,即链表的结构为front->a1->a2->...->rear
* 只有在析构函数中才删除这两个指针,其余的时间这两个指针都是存在的,其中的数据始终为0,不存储用户数据
*/
template <class T>
class LinkedList {
private:
    Node<T> *front, *rear; //表头和表尾指针
    Node<T> *prevPtr, *currPtr; //记录表当前遍历位置的指针,由插入和删除操作更新
    int size; //表中元素个数
    int position; //当前元素在表中的位置序号。由函数reset使用

    Node<T>* newNode(const T& item, Node<T> *ptrNext = NULL); //生成新节点,数据与为item,指针域为prtNext
    void freeNode(Node<T> *p); //释放节点

    void copy(const LinkedList<T>& L); //将链表L复制到当前表(假设当前表为空),被复制构造函数和operator=调用

public:
    LinkedList(); //构造函数
    LinkedList(const LinkedList<T>& L); //复制构造函数
    ~LinkedList(); //析构函数
    LinkedList<T>& operator = (const LinkedList<T>& L); //重载赋值运算符

    int getSize() const; //返回链表中元素个数
    bool isEmpty() const; //链表是否为空

    void reset(int pos = 0); //初始化游标的位置
    void next(); //使游标移动到下一个节点
    bool endOfList() const; //游标是否移动到链尾
    int currentPosition() const; //返回游标当前的位置
    
    void insertFront(const T& item); //在表头插入节点
    void insertRear(const T& item); //在表尾插入节点
    void insertAt(const T& item); //在当前节点之前插入节点
    void insertAfter(const T& item); //在当前节点之后插入节点

    T deleteFront(); //删除头节点
    void deleteCurrent(); //删除当前节点
    
    T& data(); //返回对当前节点成员数据的引用
    const T& data() const; //返回对当前节点成员数据的常引用

    void clear(); //清空链表:释放所有节点的内存空间,被析构函数和operator=使用
};

//生成新节点,数据与为item,指针域为prtNext
template <class T>
Node<T>* LinkedList<T>::newNode(const T& item, Node<T> *ptrNext) {
    Node<T> *n = new Node<T>(item, ptrNext);
    return n;
}

//释放节点
template <class T>
void LinkedList<T>::freeNode(Node<T> *p) {
    Node<T>* temp = front;
    while (temp->next != p) {
        temp = temp->next;
        if (temp == currPtr)
            position ++;
    }
    temp->next = p->next;
    if (currPtr == p)
        currPtr = currPtr->next;
    if (prevPtr == p) {
        prevPtr = prevPtr->next;
        currPtr = currPtr->next;
    }
    delete p;
    size --;
    position --;
}

//将链表L复制到当前表(假设当前表为空),被复制构造函数和operator=调用
template <class T>
void LinkedList<T>::copy(const LinkedList<T>& L) {
    Node<T> *temp = L.front, *ptr = front;
    while (temp != L.rear) {
        ptr->next = new Node<T>(temp->getData, NULL);
        ptr = ptr->next;
        temp = temp->next;
    }
    ptr->next = rear;
    size = L.getSize();
    position = L.currentPosition();
}

//构造函数
template <class T>
LinkedList<T>::LinkedList() {
    front = new Node<T>();
    rear = new Node<T>();
    front->next = rear;
    currPtr = rear;
    prevPtr = front;
    size = 0; //不计算front和rear
    position = 0; //在front下一个元素视为0
}

//复制构造函数
template <class T>
LinkedList<T>::LinkedList(const LinkedList<T>& L) {
    clear();
    copy(L);
}

//析构函数
template <class T>
LinkedList<T>::~LinkedList() {
    LinkedList::clear();
    delete front;
    delete rear;
}

//重载赋值运算符
template <class T>
LinkedList<T>& LinkedList<T>::operator = (const LinkedList<T>& L) {
    clear();
    copy(L);
}

//返回链表中元素个数
template <class T>
int LinkedList<T>::getSize() const {
    return size;
}

//链表是否为空
template <class T>
bool LinkedList<T>::isEmpty() const {
    return (size == 0);
}

//初始化游标的位置
template <class T>
void LinkedList<T>::reset(int pos) { //初始化游标位置
    if (pos > size) {
        // cout << "越界,无法访问" << endl;
        return;
    }
    int i = 0;
    prevPtr = front;
    currPtr = front->next;
    while (i < pos) {
        if (currPtr == rear) {
            // cout << "越界,无法访问" << endl;
            return;
        }
        i ++;
        currPtr = currPtr->next;
        prevPtr = prevPtr->next;
    }
    position = pos;
}

//使游标移动到下一个节点
template <class T>
void LinkedList<T>::next() {
    if (currPtr == rear) {
        // cout << "已经到达链表尾,无法移动" << endl;
        return;
    }
    currPtr = currPtr->next;
    prevPtr = prevPtr->next;
    position ++;
}

//游标是否移动到链尾
template <class T>
bool LinkedList<T>::endOfList() const {
    return (currPtr == rear);
}

//返回游标当前的位置
template <class T>
int LinkedList<T>::currentPosition() const {
    return position;
}

//在表头插入节点
template <class T>
void LinkedList<T>::insertFront(const T& item) {
    Node<T>* n = new Node<T>(item, front);
    front = n;
    size ++;
    position ++;
}

//在表尾插入节点
template <class T>
void LinkedList<T>::insertRear(const T& item) {
    Node<T>* temp = front;
    while (temp->next != rear)
        temp = temp->next;
    Node<T> *n = new Node<T>(item, rear);
    temp->next = n;
    size ++;
}

//在当前节点之前插入节点
template <class T>
void LinkedList<T>::insertAt(const T& item) {
    Node<T>* temp = new Node<T>(item, currPtr);
    prevPtr->next = temp;
    prevPtr = temp;
    size ++;
    position ++;
}

//在当前节点之后插入节点
template <class T>
void LinkedList<T>::insertAfter(const T& item) {
    Node<T>* temp = new Node<T>(item, NULL);
    temp->next = currPtr->next;
    currPtr->next = temp;
    size ++;
}

//删除头节点,实质是删除front->next
template <class T>
T LinkedList<T>::deleteFront() {
    if (front->next == rear) {
        // cout << "没有节点可以删除" << endl; 
    }
    if (prevPtr == front->next) {
        prevPtr = prevPtr->next;
        currPtr = currPtr->next;
    }
    Node<T>* temp = front->next;
    T d = temp->getData();
    front->next = temp->next;
    delete temp;
    size --;
    if (front->next != rear)
        position --;
    return d;
}

//删除当前节点
template <class T>
void LinkedList<T>::deleteCurrent() {
    Node<T>* temp = currPtr;
    currPtr = currPtr->next;
    delete temp;
    size --;
}
    
//返回对当前节点成员数据的引用
template <class T>
T& LinkedList<T>::data() {
    return currPtr->getData();
}

//返回对当前节点成员数据的常引用
template <class T>
const T& LinkedList<T>::data() const {
    return currPtr->getData();
}

//清空链表:释放所有节点的内存空间,被析构函数和operator=使用
template <class T>
void LinkedList<T>::clear() {
    Node<T>* temp;
    while (front->next != rear) {
        temp = front->next;
        front->next = temp->next;
        delete temp;
    }
    size = 0;
    position = 0;
}

/**********  Begin  **********/

template <class T>
class Queue : public LinkedList<T>
{
public:
    // Queue() {LinkedList();}
    Queue() {}
    void push(const T& item) {LinkedList<T>::insertRear(item);}
    T pop() {return LinkedList<T>::deleteFront();}
};


/**********  End  **********/

#include <iostream>
using namespace std;

int main()
{
    int item;
    Queue<int> q;
    // cout << "输入5个要插入的元素" << endl;
    for (int i = 0; i < 5; i ++) {
        cin >> item;
        q.push(item);
    }
    for (int i = 0; i < 5; i ++)
        // cout << "取出元素" << q.pop() << endl;
        cout << q.pop() << " ";
    cout<< endl;
    return 0;
}

第4关:实现含排序功能的数组类

#include <iostream>
using namespace std;

template <class T>
class Array
{
    T* alist;
    int size;
public:
    Array() {size = 0;}
    Array(int sz) {alist = new T[sz]; size = sz;}
    Array(T a[], int sz) {
        size = sz;
        alist = new T[size];
        for (int i = 0; i < size; i ++)
            alist[i] = a[i];
    }
    ~Array() {size = 0; delete []alist;}
    int getSize() {return size;}
    T& operator [](int i) {return alist[i];}
    void output(){
        for(int i = 0; i < size; i ++)
            cout << alist[i] << " ";
        cout << endl;
    }
    void insertSort();
    void selectSort();
    void bubbleSort();
    int seqSearch(T key);
};

/**********  Begin  **********/

// 在数组中顺序查找key元素,若找到则返回其索引值(是数组中第几个,从0算起),找不到则返回-1
template <class T>
int Array<T>::seqSearch(T key) {
int i;
    for (i = 0; i < size; i ++)
        if (alist[i] == key)
            return i;
    if (i == size) {
        // cout << "没有找到元素" << endl;
        return -1;
    }
    return -1;

}

// 插入排序
template <class T>
void Array<T>::insertSort(){
int i, j;
    T temp;
    //将下标为1~size-1的元素逐个插入到已排序序列中适当的位置
    for (i = 1; i < size; i ++) 
    {
        //从a[i-1]开始向a[0]方向扫描各元素,寻找适当位置插入a[i]
        j = i;
        temp = alist[i];
        while (j > 0 && temp < alist[j-1]) 
        {   //逐个比较,直到temp>=a[j-1]时,j便是应插入的位置。
            alist[j] = alist[j-1];  //将元素逐个后移,以便找到插入位置时可立即插入。
            j--;
        }
        //插入位置已找到,立即插入。
        alist[j] = temp;
    }

}

// 选择排序
template <class T>
void Array<T>::selectSort(){
int minIndex; //每一次选出的最小元素之下标
    int i, j;
    T temp;
    //sort a[0]..a[size-2], and a[size-1] is in place
    for (i = 0; i < size - 1; i ++) 
    {
        minIndex = i;    //最小元素之下标初值设为i
        //在元素a[i+1]..a[size-1]中逐个比较显出最小值
        for (j = i + 1; j < size; j++) 
            //minIndex始终记录当前找到的最小值的下标
            if (alist[j] < alist[minIndex])
                minIndex = j;
        //将这一趟找到的最小元素与a[i]交换
        temp = alist[i];
        alist[i] = alist[minIndex];
        alist[minIndex] = temp;
    }

}

template <class T>
void Array<T>::bubbleSort(){
T temp;
    int i, j;
    for (i = 1; i < size; i ++) {
        for (j = size - 1; j >= i; j --) {
            if (alist[j - 1] > alist[j]) {
                temp = alist[j];
                alist[j] = alist[j - 1];
                alist[j - 1] = temp;
            }
        }
    }

}
/**********  End  **********/

int main()
{
    int a[5] = {3, 6, 1, 8, 2};
    Array<int> iArray(a, 5);
    iArray.insertSort();
    iArray.output();

    double d[4] = {4.1, 3.2, 5.6, 1.9};
    Array<double> dArray(d, 4);
    dArray.selectSort();
    dArray.output();

    char c[3] = {'g', 'c', 'A'};
    Array<char> cArray(c, 3);
    cArray.bubbleSort();
    cArray.output();

    int b[4] = {-1, 2, 0, 5};
    Array<int> bArray(b, 4);
    cout<< bArray.seqSearch(0)<< endl;
    cout<< bArray.seqSearch(3)<< endl;
    return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值