A. DS单链表--类实现

【题目描述】

用C++语言和类实现单链表,含头结点

属性包括:data数据域、next指针域

操作包括:插入、删除、查找

注意:单链表不是数组,所以位置从1开始对应首结点,头结点不放数据

类定义参考

 

【输入】

第1行先输入n表示有n个数据,接着输入n个数据
第2行输入要插入的位置和新数据
第3行输入要插入的位置和新数据
第4行输入要删除的位置
第5行输入要删除的位置
第6行输入要查找的位置
第7行输入要查找的位置

【输出】

数据之间用空格隔开,

第1行输出创建后的单链表的数据

每成功执行一次操作(插入或删除),输出执行后的单链表数据

每成功执行一次查找,输出查找到的数据

如果执行操作失败(包括插入、删除、查找等失败),输出字符串error,不必输出单链表

【输入样例】

6 11 22 33 44 55 66
3 777
1 888
1
11
0
5
 

【输出样例】

11 22 33 44 55 66 \n
11 22 777 33 44 55 66 \n
888 11 22 777 33 44 55 66 \n
11 22 777 33 44 55 66 \n
error\n
error\n
44\n

花了一个多小时,从部分正确到AC

#include<iostream>
using namespace std;

class ListNode {//结点类
public:
	int data;//数据域
	ListNode* next;//指针域,指向后继
	ListNode() {//结点初始化
		next = NULL;//将指针置为空
	}
};
class LinkList {
public:
	ListNode* head;//创建头指针
	int len;//链表长度
	LinkList();//初始化链表
	~LinkList();//析构链表
	ListNode* LL_index(int i);//返回第i个结点的指针
	int LL_get(int i);//获取第i个数据
	int LL_insert(int i, int item);//将item插入到第i个位置
	int LL_del(int i);//删除第i个结点
	void LL_display();//输出单链表内容
};
LinkList::LinkList() {
	head = new ListNode();//创建动态链表,数据类型为ListNode结点类
	len = 0;//初始化长度
}
LinkList::~LinkList() {//逐个结点回收的原因见注释。
	ListNode * p = head, *q;
	while (p != NULL) {//只要头结点不是最后一个数据元素(指向空),就执行
		q = p;//q负责记录下一个结点,便于当前p释放后,q及时补充。(定下太子再驾崩)
		p = p->next;//如果只用一个p变量,delete后指向下一个,会出现 找不到下一个元素地址 的问题。
		delete q;
	}
	len = 0;
	head = NULL;//头结点为空,说明表已经全部清空了。
}
ListNode* LinkList::LL_index(int i) {//返回第i个结点的指针
	ListNode* p=head;
	int j = 1;
	if (i == 0) {//如果是第0个,则对应的是头指针
		return head;
	}
	p = p->next;//为什么不写在前面声明的时候?因为,存在i=0时的头结点情况,如果写在前面,就直接跳过了。
	while ((p != NULL) && (j < i)) {//不断向后移
		p = p->next;
		j++;
	}
	if ((j > i)||!p) {
		cout << "error" << endl;
		return 0;
	}
	else {
		return p;
	}
}
int LinkList::LL_get(int i) {//获取第i个数据
	if ((i <= 0) || (i > len)) {
		cout << "error" << endl;
		return 0;
	}
	ListNode* p = head->next;
	int j = 1;
	while ((p != NULL) && (j < i)) {
		p = p->next;
		j++;
	}
	if ((p == NULL) || (i < j)) {
		cout << "error" << endl;
		return 0;
	}
	else {
		cout << p->data << endl;
		return 1;
	}
}
int LinkList::LL_insert(int i, int item) {
	if (i <= 0 || i > len + 1) {//i输入不合法的情况
		cout << "error" << endl;
		return 0;
	}
	ListNode* p = LL_index(i - 1);//找到要插入的前一个结点,因为插入从这一位就要开始改变了!!
	if (p == NULL) {//i-1不存在,超出长度等其他原因!!
		cout << "error" << endl;
		return 0;
	}
	ListNode* s = new ListNode();//动态创建一个新的结点,代表了要插入的结点
	s->data = item;//结点的数据域储存插入的元素
	s->next = p->next;//建立要插入的结点的后继
	p->next = s;//建立要插入的的结点的前驱
	len++;//插入后,长度要加1!!!
	return 1;
}
int LinkList::LL_del(int i) {//删除第i个结点
	if (i <= 0 || i > len) {//判断i是否合法
		cout << "error" << endl;
		return 0;
	}
	ListNode* p = LL_index(i-1);//找到要插入的前一个结点,因为删除从这一位就要开始改变了(后继要改变)
	if (p == NULL) {//为空,或者i不合法
		cout << "error" << endl;
		return 0;
	}
	ListNode* q = p->next;//q就是要删除的那个结点
	if (q != NULL) {//为什么要多加一个这个判断?因为判断了i-1合法,你也无法保证i不是最后一位的下一位(此时不合法)
		p->next = q->next;
		delete q;
		len--;//删除后要记得减1!!!
		return 1;
	}
	else {
		cout << "error" << endl;
		return 0;
	}
}
void LinkList::LL_display() {
	ListNode* p = head->next;//从第一个有效的结点开始
	while (p) {//只要不是空结点 或者 最后一个结点的下一个
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}

int main() {
	int len;
	cin >> len;
	int item;//表示一个个数据域的元素
	LinkList mylist;
	for (int i = 1; i <= len; i++) {//完成一个个插入
		cin >> item;
		mylist.LL_insert(i, item);
	}
	mylist.LL_display();//第一行输出
	int times = 2;//插入和删除都要两次
	int i;//插入 or 删除位数
	while (times--) {
		cin >> i >> item;
		if (mylist.LL_insert(i, item)) {//为什么不能和输出并列,因为会输出好几行;已经error,就不用输出链表元素了
			mylist.LL_display();
		}
	}
	times = 2;//插入和删除都要两次
	while (times--) {
		cin >> i;
		if (mylist.LL_del(i)) {
			mylist.LL_display();
		}
	}
	times = 2;//插入和删除都要两次
	while (times--) {
		cin >> i;
		mylist.LL_get(i);
	}
	return 0;
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值