数据结构——离散存储【链表】
(第一次用markdown写笔记,有点排板就用了一个小时😢)
定义
n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点,每个节点只有一个后续节点,首节点没有前驱节点,尾节点没有后续节点。
专业术语
- 首节点:存放第一个有效数据的节点
- 尾节点:存放最后一个有效数据的节点
- 头节点:位于首节点之前的一个节点,头结点并不存放有效的数据,加头结点的目的主要是为了方便对链表的操作
- 头指针:指向头结点的指针变量
- 尾指针:指向尾节点的指针变量-
确定一个链表需要几个参数:只需要一个头指针参数,因为我们通过头指针可以推算出链表的其他所有信息
分类
单链表
双链表:每一个节点有两个指针域
循环链表:能通过一个节点找到其他所有节点
非循环链表
优缺点
- 优点:空间没有限制,插入删除元素很快
- 缺点:存取速度很慢。
代码如下
//2020.4.1/17:30
#include<iostream>
using namespace std;
typedef struct Node
{
int data;//数据域
struct Node* Next;//指针域
}NODE, *PNODE;
//从此之后 struct Node==NODE, struct Node*=PNODE;
//创建一个链表
PNODE create_list();
//遍历链表
void traverse_list(PNODE pHead);
//求链表长度
int length_list(PNODE pHead);
//在链表第pos的结点前插入数据为val的结点(pos>=1)
void insert_list(PNODE pHead, int pos, int val);
//删除链表第pos个结点,并把该结点数据赋予val输出
void delete_list(PNODE pHead, int pos, int* pval);
//排序(选择排序)
void sort_list(PNODE pHead);
int main()
{
PNODE pHead=create_list();
traverse_list(pHead);
cout << endl;
insert_list(pHead, 3, 30);
traverse_list(pHead);
cout << endl;
int val;
delete_list(pHead, 2, &val);
cout << "被删除元素为" << val << endl;
sort_list(pHead);
traverse_list(pHead);
return 0;
}
//
PNODE create_list()
{
cout << "请输入链表有效结点的个数:";
int len;
cin >> len;
if (len < 0)
{
cout << "请输入一个有效数据";
exit(-1);
}
int val;//存放用户输入的结点的值
//分配了一个不存放有效数据的头结点 并生成一个头指针指向它
PNODE pHead = (PNODE)malloc(sizeof(NODE));
//生成一个尾结点(相当于一个分身)
PNODE pTail = pHead;
pTail->Next = NULL;//尾结点的指针域为空
for (int i = 0;i < len;i++)
{
cout << "请输入链表第" << i + 1 << "个结点的值:";
cin >> val;
PNODE pNew = (PNODE)malloc(sizeof(NODE));//生成新结点
pNew->data = val;
pTail->Next = pNew;
pTail = pNew;
pNew->Next = NULL;
}
return pHead;
}
//
void traverse_list(PNODE pHead)
{
PNODE p = pHead->Next;
while (p != NULL)
{
cout << p->data << ' ';
p = p->Next;
}
}
//
int length_list(PNODE pHead)
{
int len = 0;
PNODE p = pHead->Next;
while (p)
{
len++;
p = p->Next;
}
return len;
}
//
void insert_list(PNODE pHead, int pos, int val)
{
if (pos < 0||(pos-1)>length_list(pHead)) //注意 要找到的是pos-1处的结点
{
cout << "输入pos错误";
exit(-1);
}
PNODE p = pHead;
for (int i = 0;i < pos - 1;i++)
{
p = p->Next;
}
PNODE pNew = (PNODE)malloc(sizeof(NODE));
pNew->data = val;
pNew->Next = p->Next;
p->Next = pNew;
}
void delete_list(PNODE pHead, int pos, int* pval)
{
if (pos < 0 || pos>length_list(pHead)) //注意 要找到的是pos-1处的结点||但是与插入不同
{
cout << "输入pos错误";
exit(-1);
}
PNODE p = pHead;
for (int i = 0;i < pos - 1;i++)
{
p = p->Next;
}
PNODE q = p->Next;
*pval = q->data;
p->Next = q->Next;
free(q);
}
//
void sort_list(PNODE pHead)
{
int i, j, t;
int len = length_list(pHead);
PNODE p, q;
for (i = 0, p = pHead->Next; i < len - 1; ++i, p = p->Next)
{
for (j = i + 1, q = p->Next; j < len; ++j, q = q->Next)
{
if (p->data > q->data) //类似于数组中的: a[i] > a[j]
{
t = p->data;//类似于数组中的: t = a[i];
p->data = q->data; //类似于数组中的: a[i] = a[j];
q->data = t; //类似于数组中的: a[j] = t;
}
}
}
return;
}
在最后,分享一下b站的郝斌老师,虽然我是一个菜🐶,但他对我的影响非常大。
为什么我在20年还在看10年的视频..因为我对计算机的理解还停留在00年....