链表的两个重要组成部分:
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;
}