1、定义:
n个节点离散分配;
每个节点只有一个前驱结点,每个节点只有一个后续节点;
首节点没有前驱结点,尾节点没有后续节点;
2、专业术语:
头节点:第一个有效节点之前的节点,方便对链表进行操作,并不存放有效数据,头节点的数据类型与首节点一致;
首节点:第一个有效节点;
尾节点:最后一个有效节点;
头指针:指向头节点的指针变量;
尾指针:指向尾节点的指针变量。
3、如果希望通过一个函数来对链表进行处理,我们至少需要接受链表那些信息:
只需要一个参数:头指针,通过头指针可以推算出链表的其他所有信息。
4、分类:
单链表:
双链表:每个节点有2个指针域。
循环链表:能通过任何一个节点找到所有节点。
5、算法:
遍历
查找
清空
销毁
求长度
排序
删除节点
插入节点
(要点,先临时定义一个指向p后面节点的指针r)
(在p后面插入节点q)
r = p->pNext; p->pNext = q;(p指向q) q->qNext = r;(q指向下一个节点)
q->pNext = p->pNext; p->pNext = q;
(删除p后面的节点)
r = p->pNext;
p->pNext = p->pNext->pNext;
free(r);
6、算法:
狭义的算法是与数据的存储方式密切相关的。
广义的算法是与数据的存储方式无关的。
泛型:利用某种技术达到的效果就是:不用的存储方式,执行的操作是一样的。
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node {
int data; //数据域
struct Node* pNext; //指针域,存放下一个节点的地址
} NODE , *PNODE; //NODE相当于struct Node 类型,*PNODE想当与struct Node*类型
PNODE create_List(void); //创建非循环单链表
void traverse_List(PNODE pHead);//遍历链表
bool is_Empty(PNODE pHead); //判断链表是否为空
int length_List(PNODE pHead);//求链表的长度
bool insert_List(PNODE, int, int);//向链表插入数据,第一个参数是链表的头节点,第二个参数是插入的位置,第三个是插入的值(data)
bool delete_List(PNODE, int, int*);//删除某个节点,第一个参数是链表的头节点,第二个参数是删除节点的位置,第三个是删除节点的值(data)
void sort_List(PNODE); //对链表进行排序
int main() {
PNODE pHead = NULL; //等价于 struct Node* pHead = null
pHead = create_List(); //创建一个非循环单链表,并把链表首地址赋给pHead
if (is_Empty(pHead)) {
printf("该链表为空。\n");
}
else {
printf("链表不为空。\n");
int len = length_List(pHead);
printf("链表的长度为:%d\n", len);
}
traverse_List(pHead); //遍历链表
sort_List(pHead);
traverse_List(pHead); //遍历链表
return 0;
}
PNODE create_List(void) {
int len; //链表节点个数
int val; //用来临时存放用户输入的数据data
//分配了一个不存放有效数据的头节点
PNODE pHead = (PNODE)malloc(sizeof(NODE));
if (NULL == pHead) {
printf("分配失败,程序终止!");
exit(-1);
}
//pTail与pHead都指向头节点
PNODE pTail = pHead;
//避免当链表节点个数为0,程序崩溃
pTail->pNext = NULL;
printf("请输入你要生成的链表的节点个数:");
scanf("%d", &len);
for (int i = 0; i < len; ++i) {
printf("请输入第%d个节点的数据:" , i+1);
scanf("%d", &val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if (NULL == pHead) {
printf("分配失败,程序终止!");
exit(-1);
}
pNew->data = val;
//pTali永远指向尾节点
pTail->pNext = pNew; //pTail指向新节点
pNew->pNext = NULL; //把新节点的指针域清空
pTail = pNew; //将新节点pNew放置到pTail
}
return pHead;
}
void traverse_List(PNODE pHead) {
PNODE p = pHead->pNext;
while (NULL != p) {
printf("%d ", p->data);
p = p->pNext;
}
printf("\n");
return;
}
bool is_Empty(PNODE pHead) {
if (NULL == pHead->pNext) {
return true;
}
else return false;
}
int length_List(PNODE pHead) {
PNODE p = pHead->pNext;
int len = 0;
while (NULL != p) {
len++;
p = p->pNext;
}
return len;
}
void sort_List(PNODE pHead) {
/*简单的冒泡排序
int i, j, t;
for (i = 0; i < len - 1; i++) {
for (j = i + 1; j < len; j++) {
if (a[i] > a[j]) {
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
}
return;*/
int i, j, t;
int len = length_List(pHead);
PNODE p, q;
for (i = 0, p = pHead->pNext; i < len - 1; i++, p = p->pNext) {
for (j = i + 1, q = p->pNext; j < len; j++, q = q->pNext) {
if (p->data > q->data) {
t = p->data;
p->data = q->data;
q->data = t;
}
}
}
return;
}