大连理工大学C语言题目(十一)

95 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

链表 【习题描述】 习题要求:

a. 构建一个含有头结点的链表,除头结点外的第一个结点位置为0

b. 查找值为x的结点,返回第一个值为x的结点位置,若不存在返回-1

c. 删除所有值为x的结点

d. 插入单链表的第i个结点,并判断i是否合理

e. 删除单链表的第i个结点,并判断i是否合理

f. 输入一个单链表,然后输出它的倒数第K个结点的值,计数从1开始,即,链表结尾的元素就是倒计数第1个元素,判断K是否合理

用例:

假设输入为:1 2 3 4 5 0 5 2 9 0 3 2

则输出为:

输入以 0 为结束

1 2 3 4 5

值为5的结点位置:4

1 3 4 5

9 1 3 4 5

9 1 3 5

倒数第2个结点的值3

2.实际用例输入:1 1 1 2 1 1 3 0 5 1 9999 2 0 1, 期望输出:输入以 0 为结束

1 1 1 2 1 1 3

值为5的结点位置:-1

2 3

2 3 9999

3 9999

倒数第1个结点的值9999

  1. 实际用例输入:1 1 1 2 1 5 7 1 3 0 5 1 9999 2 0 1, 期望输出:输入以 0 为结束

1 1 1 2 1 5 7 1 3

值为5的结点位置:5

2 5 7 3

2 5 9999 7 3

5 9999 7 3

倒数第1个结点的值3

  1. 实际用例输入:1 1 1 2 1 5 7 1 3 0 5 1 9999 2 0 10, 期望输出:输入以 0 为结束

1 1 1 2 1 5 7 1 3

值为5的结点位置:5

2 5 7 3

2 5 9999 7 3

5 9999 7 3

表长不够

倒数第10个结点的值-1

  1. 实际用例输入:1 1 1 2 1 5 7 1 3 0 5 1 9999 2 9999 1, 期望输出:输入以 0 为结束

1 1 1 2 1 5 7 1 3

值为5的结点位置:5

2 5 7 3

2 5 9999 7 3

非法删除点

2 5 9999 7 3

倒数第1个结点的值3

/*1.2-a-f 链表

	void createLink();				//1.2-a 以表尾添加结点的方式构建链表
	int findNode(const T& value);	//1.2-b 查找值为value的结点,返回第一个值为value的结点位置,若不存在返回-1
	void deleteValue(const T& value);//1.2-c 删除所有值为value的结点
	bool insertPos(const int i, const T value); //1.2-d 在指定位置插入结点
	bool deletePos(const int i);				//1.2-e 删除指定位置的结点
	int reFindPos(const int K);     //1.2-f 查找倒数第K个结点

*/
#include <iostream>
using namespace std;

template <class T>
class LinkNode {
public:
    T data; //数据域
    LinkNode<T>* link; //指向后继指针的结点
    LinkNode()
    {
        data = 0;
        link = NULL;
    }
    LinkNode(const T& el)
    {
        data = el;
        link = NULL;
    }
};

template <class T>
class LinkList {
private:
    LinkNode<T>*head, *tail; //表头和表尾指针
public:
    LinkList()
    {
        head = tail = NULL;
    }
    ~LinkList()
    {
        clear();
    }
    void createLink(); //1.2-a 以表尾添加结点的方式构建链表
    int getSize() const; //返回链表中的元素个数
    bool isEmpty() const; //链表是否为空
    void clear(); //清空链表:释放所有结点的内存空间

    int findNode(const T& value); //1.2-b 查找值为value的结点,返回第一个值为value的结点位置,若不存在返回-1
    void deleteValue(const T& value); //1.2-c 删除所有值为value的结点
    LinkNode<T>* setPos(int pos); //返回指定位置pos的指针
    bool insertPos(const int i, const T value); //1.2-d 在指定位置插入结点
    bool deletePos(const int i); //1.2-e 删除指定位置的结点
    int reFindPos(const int K); //1.2-f 查找倒数第K个结点
    void printList(); //输出链表
};

/*
TODO:1.2-a 以表尾添加结点的方式构建链表,输入为0时,链表构建结束。
 */
template <class T>
void LinkList<T>::createLink()
{
    LinkNode<T>* s = new LinkNode<T>;
    LinkNode<T>* p;
    this->head = s;
    this->tail = s;
    this->tail->link = NULL;
    cout << "输入以 0 为结束" << endl;
    T value;
    cin >> value;
    while (value != 0 && value != '0') //输入为0时,链表构建结束
    {
        //TODO:构建链表
        LinkNode<T>* q = new LinkNode<T>;
        q->data=value;
        tail->link=q;
        tail=q;
        tail->link= nullptr;
        cin >> value;
    }
}

//返回链表中的元素个数
template <class T>
int LinkList<T>::getSize() const
{
    int count = 0;
    LinkNode<T>* p = head->link;
    if (isEmpty())
        return 0;
    while (p != NULL) {
        p = p->link;
        count++;
    }
    return count;
}

//链表是否为空
template <class T>
bool LinkList<T>::isEmpty() const
{
    if (head->link == NULL) {
        return true;
    }
    return false;
}

//清空链表:释放所有结点的内存空间
template <class T>
void LinkList<T>::clear()
{
    LinkNode<T>* p;
    while (head != NULL) {
        p = this->head;
        head = this->head->link;
        delete p;
    }
    head = tail = NULL;
}

/*
TODO:1.2-b 查找值为value的结点,返回第一个值为value的结点位置,若不存在返回-1。
比如:假如第一个元素就是value,则返回0,依次类推
返回值说明:返回第一个值为value的结点位置,若不存在返回-1。
 */
template <class T>
int LinkList<T>::findNode(const T& value)
{
    LinkNode<T>*p=head;
    int cnt=0;
    while (p->link){
        if (p->link->data==value){
            return cnt;
        }
        p=p->link;
        cnt++;
    }
    return -1;
}

/*
TODO:1.2-c 删除所有值为value的结点

 */
template <class T>
void LinkList<T>::deleteValue(const T& value)
{
    LinkNode<T>*p=head;
    while (p->link){
        if (p->link->data==value){
            p->link=p->link->link;
        } else{
            p=p->link;
        }
    }
}

//返回指定位置pos的指针
template <class T>
LinkNode<T>* LinkList<T>::setPos(int pos)
{
    if (pos == -1)
        return head;
    int count = 0;
    LinkNode<T>* p = this->head->link;
    while (p != NULL && count < pos) {
        p = p->link;
        count++;
    }
    return p;
}

/*
TODO:1.2-d 在指定位置i插入值为value的结点,比如:i为0,表示在链表头部插入
返回值说明:如果成功插入,则返回true,否则,返回false。
注意事项:假如插入的位置i非法,即位置i处不能进行插入操作,则打印cout << "插入操作不允许" << endl;并返回false。
 */
template <class T>
bool LinkList<T>::insertPos(const int i, const T value)
{
    if (i>=0){
        LinkNode<T>*p=head;
        for (int j = 0; j < i; ++j) {
            p=p->link;
            if (!p){
                cout << "插入操作不允许" << endl;
                return false;
            }
        }
        LinkNode<T>* q = new LinkNode<T>;
        q->data=value;
        q->link=p->link;
        p->link=q;
        return true;
    } else{
        cout << "插入操作不允许" << endl;
        return false;
    }
}

/*
TODO:1.2-e 删除指定位置i处的结点
返回值说明:成功删除结点,则返回true,否则返回false。
注意事项:如果位置i处没有元素,则打印cout << "非法删除点" << endl;并返回false
 */
template <class T>
bool LinkList<T>::deletePos(const int i)
{
    if (i>=0){
        LinkNode<T>*p=head;
        for (int j = 0; j < i; ++j) {
            p=p->link;
            if (!p->link){
                cout << "非法删除点" << endl;
                return false;
            }
        }
        p->link=p->link->link;
        return true;
    } else{
        cout << "非法删除点" << endl;
        return false;
    }
}

/*
TODO:1.2-f 查找倒数第K个结点,并返回它的值。比如:K为1,表示要查找的元素是倒数第1个,也即是链表最后一个元素
返回值说明:如果查到到倒数第K个结点,则返回它的值,否则返回-1
注意事项:1)如果输入的K非法,即小于等于0,则打印cout << "非法输入" << endl;并返回-1
         2)如果输入的K非法,即大于链表长度,则打印cout << "表长不够" << endl;并返回-1
 */
template <class T>
int LinkList<T>::reFindPos(const int K)
{
    if (K>0){
        if (K>getSize()){
            cout << "表长不够" << endl;
            return -1;
        } else{
            LinkNode<T>*p=head;
            for (int i = 0; i < getSize() - K; ++i) {
                p=p->link;
            }
            return p->link->data;
        }
    } else{
        cout << "非法输入" << endl;
        return -1;
    }
}

template <class T>
void LinkList<T>::printList()
{
    LinkNode<T>* p = this->head->link;
    while (p != NULL) {
        cout << p->data << " ";
        p = p->link;
    }
    cout << endl;
}

int main()
{
    LinkList<int> l;
    l.createLink(); //创建链表
    l.printList();
    int value0, value1, value2, pos0, pos1, pos2;
    cin >> value0 >> value1 >> value2 >> pos0 >> pos1 >> pos2;
    cout << "值为" << value0 << "的结点位置:" << l.findNode(value0) << endl;
    l.deleteValue(value1); //删除值为value1的结点
    l.printList();
    l.insertPos(pos0, value2); //在pos0处插入值为value2的结点
    l.printList();
    l.deletePos(pos1); //删除pos1处的元素
    l.printList();
    cout << "倒数第" << pos2 << "个结点的值" << l.reFindPos(pos2) << endl; //查找倒数第pos2所表示的位置处的元素
    return 0;
}