数据结构(C++版)—— 单链表Ⅱ

目录

一、单链表定义

二、单链表的操作

2.1初始化操作

2.2传值操作

 2.3单链表的插入

 2.4单链表的删除

2.5单链表的查找操作

三、完整代码


一、单链表定义

       单链表是用“链式存储”(存储结构)实现了“线性结构”(逻辑结构),一个节点存储一个数据元素,各个节点间的先后关系用一个指针表示,它的优点显著,不要求大片连续的空间,改变容量方便,但是不可以随机存取,要消耗一定的空间存放指针,单链表有带头结点和不带头结点两种形式,带头结点的在使用过程中更为出色,本文重点介绍带头结点的形式。

二、单链表的操作

2.1初始化操作

typedef struct LNode
{
	int data;
	struct LNode* next;
}LNode,*LinkList;
       
//初始化一个单链表
bool InitList(LinkList & L)
{
    L = new LNode;
	if (L == NULL)
	{
		return false;
	}
	L->next = NULL;
    cout << "单链表初始化完成" << endl;
	return true;
}

int main()
{
    LinkList L; //声明一个指向单链表的指针
    InitList(L);
}

        以上三段代码块,第一段我们定义了一个LNode的结构体,包含了数据域和指向下一个节点的指针域,在末尾处我们定义了一个指向这个结构体的指针,并且在第三段我们声明了它为L,将它传给了第二段进行初始化。

        在第二段我们首先在LNode单链表上使用new关键字申请了一块空间并且让L指向它,下面我们进行了判空操作,接着L->next = NULL;是使单链表的指针域为空的操作。

2.2传值操作

//单链表的传值
LinkList Chuan(LinkList& L)
{
	int x;
	L = new LNode;
	LinkList s,  r = L;
	cout << "请传值,输入-1退出输值" << endl;
	cin >> x;
	while (x != -1)
	{
		LinkList s = new LNode;
		s->data = x;
		r->next = s;
		r = s;
		cin >> x;
	}
	r->next = NULL;
	return L;
}

        这里我们重点介绍while循环里的语句块,首先我们创建的s和r指针都是指向头结点的,下图中的第一个形态,接着由s指向一块新开辟的空间,并且使它的数据域为我们输入的x,对应下图的第二个形态,接着使r所指的头节点的指针域指针指向s所指向的新开辟的空间,最后使r等于s,即使r也指向s所指向的新开辟的空间,接着继续cin,直到我们的数据输入-1(这里可以改成任何你想要的数据)退出传值。

 2.3单链表的插入

//单链表插入
bool Cha(LinkList& L)
{
	int i, e;
	cout << "请输入要插入的位序及数据" << endl;
	cin >> i >> e;
	if (i < 1)
	{
		return false;
	}
	LNode* p;    //指针p指向当前扫描到的节点
	int j = 0;   //当前p指向的是第几个节点
	p = L;       //L指向头节点,头结点是第0个节点
	while (p != NULL && j < i - 1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
		return false;
	}
	LNode* s = new LNode;
	s->data = e;
	s->next = p->next;
	p->next = s;
	cout << "元素插入完成" << endl;
	return true;
}

关于上述代码的理解主要有两个方面。

第一块是while循环里的代码块,这里的主要目的是让我们创造的p指针指向我们要插入位序的上一个节点,p本来指向位序为0号的头结点,j记录p当前的指向,在while循环里我们让p指针进行移动至我们要插入位序的上一号节点。这里最好画图帮助我们来理解记忆。

第二块便是最下面我们的具体插入操作,我们new一个新的空间,使s指向它,将我们要插入的数据e存入这里的数据域,下面我们改变s的next指针指向下一个节点,上一个p的next指针指向s指向的那个节点,下图希望帮助理解。

 2.4单链表的删除

bool Shan(LinkList& L,int &e)
{
	int i;
	cout << "请输入要删除的位序" << endl;
	cin >> i;
	if (i < 1)
	{
		return false;
	}
	LNode* p;    //指针p指向当前扫描到的节点
	int j = 0;   //当前p指向的是第几个节点
	p = L;       //L指向头节点,头结点是第0个节点
	while (p != NULL && j < i - 1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
		return false;
	}
	LNode* q = p->next;
	e = q->data;
	p->next = q->next;
	cout << "数据删除完成" << endl;
	return true;
}

这里的while循环的作用和插入操作的作用一样,这里不再赘述。我们直接看到下面删除的具体操作,这里我们用新建指针q指向我们要删除位序的那个节点,用e来替换抹除原来在这里的数据,最后让p的next指针跨过删除位序的节点直指被删除位序的下一个节点。

2.5单链表的查找操作

//单链表的查找
LNode* GetElem(LinkList & L)
{
	int i;
	cout << "请输入要查找数据的位序";
	cin >> i;
	if (i < 0)
	{
		return NULL;
	}
	LNode* p;
	int j = 0;
	p = L;
	while (p != NULL && j < i)
	{
		p = p->next;
		j++;
	}
	cout << "您查找的数据为" << p->data << endl;
	return p;
}

其实我们上面的while循环的语句块就已经实现了按位查找的操作,只不过我们找到的是上一位罢了,同理我们要想找到我们要的这一位,使“j<i-1”变为“j<i”即可。再次强调画图帮助我们理解,我写的批注只能提供一些启示。

三、完整代码

#include<iostream>
using namespace std;

typedef struct LNode
{
	int data;
	struct LNode* next;
}*LinkList;
       
//初始化一个单链表
bool InitList(LinkList & L)
{
    L = new LNode;
	if (L == NULL)
	{
		return false;
	}
	L->next = NULL;
    cout << "单链表初始化完成" << endl;
	return true;
}

//单链表的传值
LinkList Chuan(LinkList& L)
{
	int x;
	LinkList s,  r = L;
	cout << "请传值,输入-1退出输值" << endl;
	cin >> x;
	while (x != -1)
	{
		LinkList s = new LNode;
		s->data = x;
		r->next = s;
		r = s;
		cin >> x;
	}
	r->next = NULL;
	return L;
}

//打印单链表
void Printt(LinkList L)
{
	cout << "当前单链表为" <<endl;
	LNode* p;
	p = L;
	L = NULL;
	while (p != NULL)
	{
		cout << p->data << "->";
		p = p->next;
	}
	cout << "NULL" << endl;
}

//单链表插入
bool Cha(LinkList& L)
{
	int i, e;
	cout << "请输入要插入的位序及数据" << endl;
	cin >> i >> e;
	if (i < 1)
	{
		return false;
	}
	LNode* p;    //指针p指向当前扫描到的节点
	int j = 0;   //当前p指向的是第几个节点
	p = L;       //L指向头节点,头结点是第0个节点
	while (p != NULL && j < i - 1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
		return false;
	}
	LNode* s = new LNode;
	s->data = e;
	s->next = p->next;
	p->next = s;
	cout << "元素插入完成" << endl;
	return true;
}

//单链表删除
bool Shan(LinkList& L,int &e)
{
	int i;
	cout << "请输入要删除的位序" << endl;
	cin >> i;
	if (i < 1)
	{
		return false;
	}
	LNode* p;    //指针p指向当前扫描到的节点
	int j = 0;   //当前p指向的是第几个节点
	p = L;       //L指向头节点,头结点是第0个节点
	while (p != NULL && j < i - 1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
	{
		return false;
	}
	LNode* q = p->next;
	e = q->data;
	p->next = q->next;
	cout << "数据删除完成" << endl;
	return true;
}

//单链表的查找
LNode* GetElem(LinkList & L)
{
	int i;
	cout << "请输入要查找数据的位序";
	cin >> i;
	if (i < 0)
	{
		return NULL;
	}
	LNode* p;
	int j = 0;
	p = L;
	while (p != NULL && j < i)
	{
		p = p->next;
		j++;
	}
	cout << "您查找的数据为" << p->data << endl;
	return p;
}

//求表的长度
int Length(LinkList L)
{
	int len = 0;
	LNode* p = L;
	while (p->next != NULL)
	{
		p = p->next;
		len++;
	}
	return len;
}

int main()
{
	LinkList L; //声明一个指向单链表的指针
	int e = 0;
	InitList(L);
	Chuan(L);
	Printt(L);
	GetElem(L);
	Cha(L);
	Printt(L);
	Shan(L, e);
	Printt(L);
	cout << "表的长度为" << Length(L) << endl;
	system("pause");
	return 0;
}

脚印,它标志着自己走过的路。我宁愿曲折,不愿在某处徘徊。成长的道路,必须有承受挫折的勇气,唯有播种努力与汗水,才能收获成功与快乐。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值