数据结构学习~04.关于单链表的归并以及头尾插入问题后续~

数据结构学习~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);

}

猜你喜欢

转载自blog.csdn.net/qq_41424688/article/details/107399270