链表
定义:
typedef int ElemType;
typedef struct Node {
ElemType data;
}Node, *LinkList;
初始化单链表
bool InitList(LinkList& L) {
L = (LinkList)malloc(sizeof(struct Node));
if (L == NULL)
return false;
L->next = NULL;
return false;
}
按位插入(带头结点)
在第 i 个位置插入,应找到第 i - 1 个位置
bool ListInsert(LinkList& L, int i, ElemType e) {
if (i < 1) {
printf("插入位置不合法!"); return false;
}
Node* p; //指针p指向当前扫描到的节点
int j = 0; //当前p指向的是第几个节点
p = L; //L指向头节点,头节点是第0个节点
while (p != nullptr && j < i - 1) {
//循环到第i-1个节点
p = p->next;
j++;
}
//或者使用指定节点的后插操作代替下方代码
//例如:
// return InsertNextNode(p,e);
if (p == nullptr) {
printf("插入位置不合法!"); return false;
}
Node* s = (Node*)malloc(sizeof(struct Node));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
指定节点的后插操作
bool InsertNextNode(Node* p, ElemType e) {
if (p == NULL)
return false;
Node* s = (Node*)malloc(sizeof(struct Node));
if (s == NULL)
return false;
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
指定节点的前插操作
思想:本质上后插,进行一次数据交换
bool InsertPriorNode(Node* p, Node* s) {
if (p == NULL || s == NULL)
return false;
s->next = p->next;
p->next = s;
ElemType temp = p->data;
p->data = s->data;
s->data = temp;
return true;
}
按位序删除
bool ListDelete(LinkList& L, int i, ElemType& e) {
if (i < 1)
return false;
Node* p; //指针p指向当前扫描到的节点
int j = 0; //指针p当前指向的是第几个节点
p = L; //L指向头节点,头节点是第0个节点
while (p!= nullptr && j<i-1) {
p = p->next;
j++;
}
if (p == NULL || p->next == nullptr)
return false;
Node* q;
q = p->next;
e = q->data;
p->next = q->next;
free(q);
return true;
}
指定节点的删除
bool DeleteNode(Node* p) {
if (p == NULL)
return false;
Node* q = p->next;
p->data = q->data;
p->next = q->next;
free(q);
return true;
}
存在bug:如果p是最后一个节点,我们只能从前往后找到他的前驱节点
按位查找,返回第i个元素
Node* GetElem(LinkList L, int i) {
if (i < 0)
return NULL;
Node* p;
int j = 0;
p = L;
while (p!=nullptr && j<i){
p = p->next;
j++;
}
return p;
}
*封装(基本操作)的好处
在第i个位置插入元素e可以改写为:
bool ListInsert(LinkList& L, int i, ElemType e){
if (i < 1) {
printf("插入位置不合法!"); return false;
}
Node* p = GetElem(L,i-1);
return InsertNextNode(p,e);
}
按值查找
Node* LocateElem(LinkList L, ElemType e) {
Node* p = L->next;
while (p != NULL && p->data!= e) {
p = p->next;
}
return p;//如果没找到,返回NULL
}
求表的长度
int Length(LinkList L) {
int len = 0;
Node* p = L;
while (p->next != NULL) {
p = p->next;
len++;
}
return len;
}
单链表的建立
1.尾插法建立单链表
LinkList TailInsert(LinkList& L) {
int x;
L = (LinkList)malloc(sizeof(struct Node));
Node* s, * r = L;
scanf("%d", &x);
while (x != 9999) { //等于9999时停止
s = (Node*)malloc(sizeof(struct Node));
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = NULL;
return L;
}
2.头插法建立单链表
LinkList HeadInsert(LinkList& L) {
Node* s;
int x;
L = (LinkList)malloc(sizeof(struct Node));
L->next = NULL; //此步骤必须有
scanf("%d", &x);
while (x != 9999) { //输入9999代表结束
s = (Node*)malloc(sizeof(struct Node)); //创建新节点
s->data = x;
s->next = L->next;
L->next = s;
scanf("%d", &x);
}
return L;
}
*头插法的重要应用:链表的倒置