单链表的形式:
单链表的每节点中除了数据域外,还包含一个指针域,用来指向下一个节点,主要有带头结点和不带头结点两种。
单链表定义如下:
//单链表结构体定义
typedef struct LNode {
int data;
struct LNode* next;
}LNode;
单链表中的两种基本算法:
插入操作:
.不妨设在节点A和节点B直间插入节点S,则具体分两步实现:
- 节点S指向节点B,
//让节点S指向B S->next = A->next;
- 节点A指向S
//节点A指S A->next = S
注意,这两步的顺序不能弄反,否则会丢失数据;
删除操作:
同理,不妨设删除节点B,则只需要找到前一个节点A即可,具体实现如下:
//p是要删除的节点 p = A->next; A->next = A->next->next; //释放节点B的空间 free(p);
具体的相关算法实现:
头插法建立单链表:
插入的新节点在表头,旧的节点在新节点之后,不妨设已有头节点B,现插入节点A,则形式为A->B,关键代码如下所示:
A->next = B->next; B->next=A;
具体实现如下:
//插入的节点在表头
STATUS CreateListOfF(LNode *&P, int a[], int n) {
//s用来指向新申请的节点
LNode* s;
int i;
//申请P的头结点
P =(LNode*) malloc(sizeof(LNode));
P->next = NULL;
for (i = 0; i < n; i++) {
s = (LNode*)malloc(sizeof(LNode));
s->data = a[i];
//新节点指向旧节点
s->next = P->next;
//新节点称为新的开始节点
P->next = s;
}
return OK;
}
尾插法建立单链表如下所示:
关键在于新插入的节点在链表的尾部,不妨设最后插入的节点是F,则最后必须加上F->next = NULL,具体实现如下:
//插入的节点在表尾
STATUS CreateListOfR(LNode *&P, int a[], int n) {
//s指向新申请的节点,r直线链表的终端节点
LNode *s,*r;
int i;
//头结点的申请
P = (LNode*)malloc(sizeof(LNode));
P->next = NULL;
r = P;
for (i = 0; i < n; i++) {
s = (LNode*)malloc(sizeof(LNode));
s->data = a[i];
//r指向终端节点
r->next = s;
r = s;
}
r->next = NULL;
return OK;
}
打印链表元素:
STATUS PrintList(LNode *P) {
if (P->next == NULL) {
return ERROR;
}
while (P->next != NULL) {
cout << P->next->data << "\t";
P = P->next;
}
cout << endl;
return OK;
}
查找某个元素并将其删除:
删除元素两个关键点:
- 待删除节点的查找;
- 待删除节点的前驱节点;
具体实现如下:
STATUS FindAndDel(LNode *&P,int x) {
//pre指向待删除节点的前一个节点
LNode *pre, *p;
p = P->next;
pre = P;
while (p != NULL) {
if (p->data == x) {
break;
}
pre = p;
p = p->next;
}
//查找部分结束
if (p == NULL) {
return ERROR;
}
else {
//让p前驱节点指向p后继节点
pre->next = p->next;
free(p);
return OK;
}
}
将两个有序递增链表A、B合并成一个递增有序链表C:
递增有序链表在这使用尾插法,将两个有序的链表的元素一一比较,将较小的一个插入C中,依次递推。
注意: A和B中的元素有可能一个已经完全插入,另外一个部分插入。不妨设A完全插入,B部分插入,这说明B的剩下元素完全大于B,这是只需要将B接入C即可;
具体实现如下:
STATUS MergeListRise(LNode *A, LNode *B, LNode *&C) {
LNode *pA = A->next;
LNode *pB = B->next;
C = A; C->next = NULL;
//r始终指向C节点
LNode *r;
r = C;
free(B);
while (pA != NULL&&pB != NULL) {
if (pA->data <= pB->data) {
r->next = pA;
r = pA; pA = pA->next;
}
else {
r->next = pB;
r = pB; pB = pB->next;
}
}
r->next = NULL;
//处理有一部分插完而另外一部分未插完;
if (pA != NULL) {
r->next = pA;
}
if (pB->next != NULL) {
r->next = pB;
}
return OK;
}
将两个有序递增链表A、B合并成一个递减有序链表C:
同上述合并成一个递增有序链表类似,但这里使用头插法构建C,不需要r指针指向C的尾节点,具体实现如下:
STATUS MergeListFall(LNode *A, LNode *B, LNode *&C) {
LNode *pA = A->next;
LNode *pB = B->next;
C = A;
C->next = NULL;
free(B);
//s指向待插入的节点
LNode *s;
while (pA!=NULL&&pB!=NULL)
{
if (pA->data <= pB->data) {
//取得待插入节点s
s = pA;
pA = pA->next;
s->next = C->next;
C->next = s;
}
else
{
s = pB;
pB = pB->next;
s->next = C->next;
C->next = s;
}
}
//当某一个链表先处理完时
while (pA != NULL)
{
s = pA;
pA = pA->next;
s->next = C->next;
C->next = s;
}
while (pB != NULL)
{
s = pB;
pB = pB->next;
s->next = C->next;
C->next = s;
}
return OK;
}
来源:https://www.cnblogs.com/zuixime0515/p/9611522.html