数据结构---单链表基本操作

链表的两个重要组成部分:
1.数据域
2.指针域

链表的基本操作:
1.初始化链表
2.前插法
3.后插法
4.打印链表
5.指定位置插入
6.获取指定位置的元素
7.根据值查询元素所在的位置
8.删除指定位置的元素
9.销毁链表

完整代码在最后

自己的感想:
链表就是一个由数据和指针组成的一个结构体,数据域里存放数据,指针域中存放指向下一个节点,然后形成一个逻辑上的链条,通过指针就可以遍历所有的数据。

1.数据的初始化:将头结点的指针域设置为NULL

typedef struct LinkNode{
    
    
	int date;  //数据域
	LinkNode* next;
}LinkList,LinkNode; //分别表示链表头和节点

bool initLinkList(LinkList* &L) {
    
    
	L = new LinkList;
	if (!L) {
    
     cout << "出错了" << endl;
		return false; }
	L->next = NULL;
	L->date = -1;
	return true;
}

2.前插法:
顾名思义,就是把数据往头结点的后面插,这样的好处就是插入数据完成后,遍历数据时,数据是倒叙存放的.
原理:就是让新结点的指针指向原来的头结点指向的节点,然后头结点再指向新结点

bool LinkInserct_front(LinkList* &L, LinkNode* node) {
    
    
	if (!L || !node)
	{
    
    cout << "出错了" << endl;
		return false;	}
	node->next = L->next;
	L->next = node;
	return true;
}

在这里插入图片描述

3.后插法:
就是把结点都插到最后一个节点的后面;
原理:先定义一个节点指向头结点,让它来寻找最后的节点的位置,然后让最后一个节点的指针指向新节点,再把新节点的指针设置为NULL
在这里插入图片描述

bool LinkInserct_back(LinkList*& L, LinkNode* node) {
    
    
	if (!L || !node)
	{
    
    	cout << "出错了" << endl;
		return false;}
	LinkNode* last;
	last = L; //注意这里应该是用指向L,
			  //而不是指向L->next,因为当一开始没有节点的时候
			  //如果用L->next,那么后面就超出范围了
	while (last->next) {
    
    
		last = last->next;
	}
	last->next = node;
	node->next = NULL;
	return true;
}

4.打印链表
就是通过一个节点遍历所有的节点,通过指针不但遍历;

bool Link_print(LinkList*& L) {
    
    
	LinkNode* f = NULL;
	f = L->next;
	while (f) {
    
    
		cout << f->date << "\t";
		f = f->next;
	}
	cout << endl;
	return 0;
}

5.指定位置插入:
原理:通过定义一个节点,并让他指向头结点,让它不断的向后遍历数据,每访问一个index就+1,直到访问到要插入位置的前一个节点t,然后使新节点的指针指向原来节点t指向的下一个节点,然后再让t指向新节点

bool LinkInserct(LinkList*& L, int i, int e) {
    
    
	if (!L)
	{
    
    cout << "出错了" << endl;
		return false;}
	LinkNode* f;
	LinkNode* s;
	int j = 0;
	f = L;
	while (f && (i - 1 > j)) {
    
    
		f = f->next;
		j++;
	}
	if (!f || (i - 1 < j)) {
    
    
		cout << "插入失败!" << endl;
		return false;
	}
	s = new LinkNode;
	s->date = e;
	s->next = f->next;
	f->next = s;
	return true;
}

在这里插入图片描述

6.获取指定位置的元素:
原理:同理定义一个新节点指向头结点,来遍历链表,它与插入不同的是,它是指向指定位置,而不是前一个位置,因为它要读取数据,读取数据后,将数据通过引用传递给e,这里简单的固定了第二个元素
实际操作可以使用定义变量来获取任意的值

bool Link_GetElem(LinkList*& L,int i,int &e) {
    
    
	//根据指定位置获取元素
	if (!L || !(L->next))						
		return false;
	int index = 1;
	LinkList* p;
	p = L->next;
	while (p && index < i) {
    
    
		p = p->next;
		index++;
	}
	if (!p || index > i)
		return false;
	e=p->date;
	return true;
}

在这里插入图片描述

7.根据值查询元素所在的位置:
原理:通过节点不断遍历,寻找与所找的值相同的数据,在寻找的时候,每访问一次,dex就+1,表示访问了几个,就表示要寻找的元素在第几个位置上.

bool Link_FindElem(LinkList* &L,int e,int &index) {
    
    
	//单链表根据值查询元素所在的位置
	if (!L || !(L->next))						
		return false;
	int dex = 1;
	LinkList* p = L->next;
	while (p && (e != p->date)) {
    
    
		p = p->next;
		dex++;
	}
	if (!p) 
	return false;
	index = dex;
	return true;
}

在这里插入图片描述

8.删除指定位置的元素
原理:定义一个节点t让其指向头结点,不断访问其他节点,然后找到要删除节点的前一个节点,然后再定义一个节点q,让q指向要删除的节点,再让t指向q的指针域,就是指向q的下一个节点,这样就没有指向q的节点了,再将其内存释放掉;`

bool LinkDelete_index(LinkList* &L,int i) {
    
    
	if (!L || !(L->next))
		return false;
	LinkList* p = L;
	int index=0;
	while (p && index < i - 1) {
    
    
		p = p->next;
		index++;
	}
	if (!p || index > i - 1) {
    
    
		return false;
	}
	LinkList* q = p->next;
	p->next = q->next;
	delete q;
	return true;
}

在这里插入图片描述

9.销毁链表*

bool LinkDestroy(LinkList*& L) {
    
    
	LinkList* p=L;
	cout << "销毁列表" << endl;
	while (p) {
    
    
		L = L->next;
		delete p;
		p = L;
	}
	return true;
}

完整的代码:

#include<iostream>
#include<Windows.h>
using namespace std;
typedef struct LinkNode{
    
    
	int date;  //数据域
	LinkNode* next;
}LinkList,LinkNode; //分别表示链表头和节点
bool initLinkList(LinkList* &L) {
    
    
	L = new LinkList;
	if (!L) {
    
     cout << "出错了" << endl;
		return false; }
	L->next = NULL;
	L->date = -1;
	return true;
}
bool LinkInserct_front(LinkList* &L, LinkNode* node) {
    
    
	if (!L || !node)
	{
    
    cout << "出错了" << endl;
		return false;	}
	node->next = L->next;
	L->next = node;
	return true;
}
bool LinkInserct_back(LinkList*& L, LinkNode* node) {
    
    
	if (!L || !node)
	{
    
    	cout << "出错了" << endl;
		return false;}
	LinkNode* last;
	last = L; //注意这里应该是用指向L,
			  //而不是指向L->next,因为当一开始没有节点的时候
			  //如果用L->next,那么后面就超出范围了
	while (last->next) {
    
    
		last = last->next;
	}
	last->next = node;
	node->next = NULL;
	return true;
}
bool Link_print(LinkList*& L) {
    
    
	LinkNode* f = NULL;
	f = L->next;
	while (f) {
    
    
		cout << f->date << "\t";
		f = f->next;
	}
	cout << endl;
	return 0;
}
bool LinkInserct(LinkList*& L, int i, int e) {
    
    
	if (!L)
	{
    
    cout << "出错了" << endl;
		return false;}
	LinkNode* f;
	LinkNode* s;
	int j = 0;
	f = L;
	while (f && (i - 1 > j)) {
    
    
		f = f->next;
		j++;
	}
	if (!f || (i - 1 < j)) {
    
    
		cout << "插入失败!" << endl;
		return false;
	}
	s = new LinkNode;
	s->date = e;
	s->next = f->next;
	f->next = s;
	return true;
}
bool Link_GetElem(LinkList*& L,int i,int &e) {
    
    
	//根据指定位置获取元素
	if (!L || !(L->next))						
		return false;
	int index = 1;
	LinkList* p;
	p = L->next;
	while (p && index < i) {
    
    
		p = p->next;
		index++;
	}
	if (!p || index > i)
		return false;
	e=p->date;
	return true;
}
bool Link_FindElem(LinkList* &L,int e,int &index) {
    
    
	//单链表根据值查询元素所在的位置
	if (!L || !(L->next))						
		return false;
	int dex = 1;
	LinkList* p = L->next;
	while (p && (e != p->date)) {
    
    
		p = p->next;
		dex++;
	}
	if (!p) 
	return false;
	index = dex;
	return true;
}
bool LinkDelete_index(LinkList* &L,int i) {
    
    
	if (!L || !(L->next))
		return false;
	LinkList* p = L;
	int index=0;
	while (p && index < i - 1) {
    
    
		p = p->next;
		index++;
	}
	if (!p || index > i - 1) {
    
    
		return false;
	}
	LinkList* q = p->next;
	p->next = q->next;
	delete q;
	return true;
}
bool LinkDestroy(LinkList*& L) {
    
    
	LinkList* p=L;
	cout << "销毁列表" << endl;
	while (p) {
    
    
		L = L->next;
		delete p;
		p = L;
	}
	return true;
}
int main() {
    
    
	LinkList* L=NULL;
	LinkNode* s = NULL;
	//1.初始化链表
	initLinkList(L);
	//2.前插法
	int n;
	cout << "前插法要插入的数据个数:" << endl;
	cin >> n;
	cout << "请输入要插入的数据:\n";
	while (n) {
    
    
		s = new LinkNode;
		cin >> s->date;
		LinkInserct_front(L,s);
		n--;
	}
	//3.尾插法
	int n;
	cout << "尾插法插入的数据个数:" << endl;
	cin >> n;
	cout << "请输入要插入的数据:\n";
	while (n) {
    
    
		s = new LinkNode;
		cin >> s->date;
		LinkInserct_back(L, s);
		n--;
	}
	//4.打印链表
	Link_print(L);
	//5.指定位置插入
	int x, e;
	for (int i = 0;i < 3;i++) {
    
    
		cout << "请输入插入位置和元素:";
		cin >> x >> e;
		LinkInserct(L, x, e);
		Link_print(L);
	}
	//6.获取指定位置的元素
	int elemt=0;
	if (Link_GetElem(L, 2, elemt)) {
    
    
		cout << "第二个元素获取成功,值为:" << elemt << endl;
	}
	else {
    
    
		cout << "第二个元素获取失败" << endl;
	}
	//7. 单链表根据值查询元素所在的位置
	int index;
	if (Link_FindElem(L, 10, index)) {
    
    
		cout << "元素10查找成功,在第" << index << "个位置上" << endl;
	}
	else {
    
    
		cout << "没有找到要查的元素!" << endl;
	}
	//8. 单链表删除指定位置的元素
	if (LinkDelete_index(L, 2)) {
    
    
		cout << "第二个元素删除成功!" << endl;
		Link_print(L);
	}
	else {
    
    
		cout << "第二个元素删除失败!" << endl;
	}
	//9.销毁链表
	LinkDestroy(L);
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_49324123/article/details/111165590