数据结构学习~04.关于单链表的归并以及头尾插入问题后续~
本文是上一篇文章的后续,详情点击该链接~
在上一篇呢,我们对单链表的合并,以及头尾插入已经有了一个最基本的认识。那么现在呢,我们就来实现使用 头插法来进行单链表的合并操作。代码呢,就接着上一篇的来,可以直接在上一篇文章的最下方复制粘贴。
头插法合并两个单链表
void headmerge(Node *A,Node *B, Node*&C) {
Node* p = A->next;
Node* q = B->next;
Node* s;
C = A;
C->next = NULL;
free(B);
while (p != NULL && q != NULL) {
if (p ->data <= q->data) {
s = p;
p = p->next;
s->next = C->next;
C->next = s;
}
else {
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
}
while (p != NULL) {
s = p;
p = p->next;
s->next = C->next;
C->next = s;
}
while (q != NULL) {
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
}
相比于上一篇的尾插,这一次的结果完全相反。
与插入结点相对应的是删除结点,其实也比较简单。假如说我要将单链表的第i个结点删除,你就必须先去找到第i-1个结点。再删除其后继结点
就举个例子,假如链表有a,b,c三个结点。用户现在想要删除结点b,那么现在,我们就需要找到结点a,然后改变a的指针方向,让它不再指向b而是指向c,最后我们使用free释放掉b就好了。
q = p->next
p->next = p->next->next
free(q)
查找并删除结点的代码操作
int Delete(Node* C, int s) {
Node* p, * q;
p = C;
//开始查找
while (p->next != NULL) {
if (p->next->data == s) {
break;
}
p = p->next;
}
if (p->next == NULL) {
return 0;
}
else {
//开始删除
q = p->next;
p->next = p->next->next;
free(q);
return 1;
}
}
奉上完整代码~
#include<stdio.h>
#include<stdlib.h>
typedef struct no_de {
int data; //data中存放数据域
struct no_de* next; //指向后继结点的指针
}Node;
//创建链表头节点,并初始化
Node* getHead();
//插入链表元素到尾部
void Insert(Node *list,int data);
//遍历链表
void Print(Node *list);
//尾插归并
void merge(Node* A, Node* B, Node*& C);
//数组尾插链表
void CreateListR(Node *&C,int *a,int n);
//数组头插链表
void CreateListF(Node*& C, int* a, int n);
//头插归并
void headmerge(Node* A, Node* B, Node*& C);
//删除节点
int Delete(Node*C,int index);
int Delete(Node* C, int s) {
Node* p, * q;
p = C;
//开始查找
while (p->next != NULL) {
if (p->next->data == s) {
break;
}
p = p->next;
}
if (p->next == NULL) {
return 0;
}
else {
//开始删除
q = p->next;
p->next = p->next->next;
free(q);
return 1;
}
}
void CreateListF(Node*& C, int* a, int n) {
Node* s; int i;
C = getHead();
for (i = 0; i < n; ++i) {
s = (Node*)malloc(sizeof(Node));
s->data = a[i];
//s所指新结点的指针域 next 指向C中的开始结点
s->next = C->next;
//头结点的指针域next指向s结点,使得s成为新的开始结点
C->next = s;
}
}
void CreateListR(Node*& C, int* a, int n) {
//s用来指向新申请的结点,r指向C的终端结点
Node* s, * r;
int i;
//申请C的头节点空间
C = getHead();
//r指向头节点,这个时候头结点就是终端结点
r = C;
for (i = 0; i < n; ++i) {
//s指向新申请的结点
s = getHead();
//新申请的结点来接收a中的一个元素
s->data = a[i];
//用r来接纳新结点
r->next = s;
//r指向终端结点,以便于接纳下一个到来的结点
r = r->next;
}
r->next = NULL;
}
void merge(Node *A,Node *B,Node *&C) {
//用amin来跟踪A的最小值结点
Node* amin = A->next;
//用bmin来跟踪B的最小值结点
Node* bmin = B->next;
//用last始终指向C的终端结点
Node* last;
//用A的头节点来做C的头结点
C = A;
C->next = NULL;
//B的头节点无用,所以我们释放它
free(B);
//last指向C,此时头节点指向终端结点
last = C;
//当amin和bmin都不为空的时候,我们就取较小的结点插入到C的尾部
while (amin != NULL && bmin != NULL) {
if (amin->data <= bmin->data) {
last->next = amin;
amin = amin->next;
last = last->next;
}
else {
last->next = bmin;
bmin = bmin->next;
last = last->next;
}
}
//这里还需要注意,A和B两个元素有可能会出现这种情况
//比如A的元素已经全部插入到C中,而B还没有插完。或者B插完A没插完
//这个时候没插完的元素基本上是大于C中的元素。所以这里呢
//这两个if就是解决这个问题的。
if (amin != NULL) {
last->next = amin;
}
if (bmin != NULL) {
last->next = bmin;
}
}
Node* getHead() {
Node* head = (Node*)malloc(sizeof(Node));
head->data = NULL;
head->next = NULL;
return head;
}
void Insert(Node *list, int data) {
Node* node = (Node*)malloc(sizeof(Node));
node->data = data;
node->next = list->next;
list->next = node;
}
void Print(Node* list) {
//如果链表是空就打印 []
if (list->next == NULL || list == NULL) {
printf("[ ]");
return;
}
Node* node = list->next;
printf("[ ");
while (node != NULL) {
//判断是否到了最后一个元素
if (node->next != NULL) {
printf("%d ,",node->data);
}
else {
//到了最后一个元素的时候就不加 ,
printf("%d ]", node->data);
}
node = node->next;
}
printf("\n");
}
void headmerge(Node *A,Node *B, Node*&C) {
Node* p = A->next;
Node* q = B->next;
Node* s;
C = A;
C->next = NULL;
free(B);
while (p != NULL && q != NULL) {
if (p ->data <= q->data) {
s = p;
p = p->next;
s->next = C->next;
C->next = s;
}
else {
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
}
while (p != NULL) {
s = p;
p = p->next;
s->next = C->next;
C->next = s;
}
while (q != NULL) {
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
}
int main(int argc,char*argv[]) {
Node* A = getHead();
Node* B = getHead();
//===============================
printf("链表1: ");
for (int i = 1; i < 10; i++) {
Insert(A, (i * 2));
}
Print(A);
//===============================
printf("链表2: ");
for (int i = 1; i < 10; i++) {
Insert(B, (i * 3));
}
Print(B);
//===============================
Delete(A, 8);
printf("删除元素8之后: ");
Print(A);
//===============================
printf("合并后: ");
Node* C = getHead();
headmerge(A,B,C);
Print(C);
}