C语言 双向链表的所有操作

整理了双链表,双向链表结点里面含有两个指针,前指针和后指针

在对链表进行改动时要注意的头结点的前指针为NULL。

双链表的插入,删除与单链表的不同是需要判断插入的后一个结点是否为空,为空的话没有前指针

------------------------------------------------------------------------------------------------------------------

主要函数有:

求长度,插入,删除,交换,查找,清除,倒置
冒泡排序(对数据进行排序)
冒泡排序(对链表进行排序)

以下是代码:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define SEP "----------------------------------------------"
//双向链表
typedef struct node {
	int data;
	struct node* pre;
	struct node* next;
}Node, *LinkList;
//双向链表结点的结构,里面含有两个指针
//用数组对双链表进行尾插法创建
LinkList CreateList(LinkList L, int*a, int len) {
	LinkList p, q;
	L = (LinkList)malloc(sizeof(Node));
	L->data = 0;
	L->pre = 0;//双链表头结点的前指针要指向NULL
	q = L;
	for (int i = 0; i < len; i++) {
		p = (LinkList)malloc(sizeof(Node));
		p->data = *(a + i);
		q->next = p;
		p->pre = q;
		q = p;
	}
	q->next = 0;
	return L;
}
void PrintList(LinkList L) {
	LinkList p = L;
	printf("数据\t前结点\t\t后结点\n");
	while (p) {
		printf("%-4d  %p\t%p\n", p->data, p->pre, p->next);
		p = p->next;
	}
	printf("%s\n", SEP);
}
//在链表的前面添加数据
LinkList addhead(LinkList L, int data) {
	LinkList p = (LinkList)malloc(sizeof(Node));
	p->data = data;
	if (!L) {
		L = p;
		p->next = 0;
		p->pre = 0;
	}
	else {
		p->next = L->next;
		//在这里需注意,若头结点后面的结点不为NULL时,前指针要指向插入的p
		if (L->next)
			L->next->pre = p;
		L->next = p;
		p->pre = L;
	}
	return L;
}
//求出当前链表的长度
int getlen(LinkList L) {
	LinkList p = L;
	int cnt = 0;
	while (p) {
		cnt++;
		p = p->next;
	}
	return cnt;
}
LinkList getNode(LinkList L, int i) {
	LinkList p = L;
	for (int j = 0; j < i&&p; j++) {
		p = p->next;
	}
	return p;
}
LinkList swap(LinkList L, int a, int b) {
	int len = getlen(L);
	LinkList apre, anode, anext, bpre, bnode, bnext;
	if (a == b || a> len || a < 1 || b<1 || b>len)
		return L;
	else {
		if (abs(a - b) == 1) {
			if (a < b)
				anode = getNode(L, a - 1);
			else
				anode = getNode(L, b - 1);
			anext = anode->next->next;
			anode->next->next = anext->next;
			anext->next = anode->next;
			anode->next = anext;
			//先安顿好后结点,再去管前结点
			if (anext->next->next) {
				anext->next->next->pre = anext->next;
			}
			anext->next->pre = anext;
			anext->pre = anode;
		}
		else {
			//当a与b不相邻的情况
			apre = getNode(L, a - 1);
			bpre = getNode(L, b - 1);
			anode = apre->next;
			bnode = bpre->next;
			anext = anode->next;
			bnext = bnode->next;

			apre->next = bnode;
			bnode->next = anext;
			bpre->next = anode;
			anode->next = bnext;
			if (anext)
				anext->pre = bnode;
			if (bnext)
				bnext->pre = anode;
			anode->pre = bpre;
			bnode->pre = apre;
		}
	}
	return L;
}
//长度,插入,删除,交换,查找,清除,倒置
//冒泡排序(对数据进行排序)
//冒泡排序(对链表进行排序)

//以下是链表的插入,删除,清除,与单链表的不同是需要判断插入的后一个结点是否为空,为空的话没有前指针
//插入时,若选取的结点大于链表的结点数,则把插入的值放到链表的最后面
LinkList InsertNode(LinkList L, int i, int data) {
	LinkList p = L, pre, q;
	for (int j = 0; j < i&&p; j++) {
		pre = p;
		p = p->next;
	}
	q = (LinkList)malloc(sizeof(Node));
	q->data = data;

	if (p) {
		q->next = p;
		q->pre = pre;
		p->pre = q;
		pre->next = q;
	}
	else {
		pre->next = q;
		q->pre = pre;
		q->next = p;
	}
	return L;
}

LinkList DeleteData(LinkList L, int data) {
	LinkList p = L, pre;
	while (p->data != data&&p) {
		pre = p;
		p = p->next;
	}
	if (p->data == data) {
		pre->next = p->next;
		p->pre = pre;
		if (!p)
			p->next->pre = pre;
		free(p);
	}
	else {
		return L;
	}
	return L;
}

//让其除了头结点以外,其他结点倒置
LinkList ReverseList(LinkList L) {
	LinkList p, q, temp;
	p = L->next;
	q = 0;
	while (p) {
		temp = p->next;
		p->next = q;
		if (q)
			q->pre = p;
		q = p;
		p = temp;
	}
	L->next = q;
	q->pre = L;
	return L;
}

//只让链表的数据域进行交换
void BumbleSort(LinkList L) {
	LinkList p = L->next;
	int a[40] = { 0 }, cnt = 0;
	//先把双链表的数据存到数组里面,在数组里进行交换后再返还
	while (p) {
		a[cnt++] = p->data;
		p = p->next;
	}
	for (int i = 0; i < cnt; i++) {
		for (int j = 0; j < cnt - 1 - i; j++) {
			if (a[j] > a[j + 1]) {
				int temp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = temp;
			}
		}
	}
	p = L->next;
	for (int i = 0; i < cnt; i++) {
		p->data = a[i];
		p = p->next;
	}
}
//让链表的结点进行交换
void BumbleSort1(LinkList L) {
	LinkList p, q, temp, end;
	p = L;
	for (end = 0; end != L; end = temp) {
		for (temp = p = L; p->next->next != end; p = p->next) {
			if (p->next->data > p->next->next->data) {
				q = p->next->next;
				p->next->next = q->next;
				q->next = p->next;
				p->next = q;
				temp = p->next->next;
				if (q->next->next) {
					q->next->next->pre = q->next;
				}
				q->next->pre = q;
				q->pre = p;
			}
		}
	}
}


void InitList(LinkList L, int*a, int len) {
	LinkList p = L->next;
	for (int i = 0; i < len; i++) {
		p->data = a[i];
		p = p->next;
	}
}

void ClearList(LinkList L) {
	LinkList p = L, q;
	while (p) {
		q = p->next;
		free(p);
		p = q;
	}
	p = 0;
}

int main() {
	int a[] = { 23,53,21,525,5 };
	int len = sizeof(a) / sizeof(int);
	int num1, num2;
	LinkList L = 0;//在用函数进行赋值时,一定要将声明的链表设为空值
	L = CreateList(L, a, len);
	//这里指针变量显示的大小有区别:64位编译器的指针是8 byte,32位编译器的指针大小是4 byte
	PrintList(L);

	printf("对链表的数据进行冒泡排序后(数据域版):\n");
	BumbleSort(L);
	PrintList(L);

	printf("对链表还原后:\n");
	InitList(L, a, len);
	PrintList(L);

	printf("对链表的结点进行冒泡排序后(结点版):\n");
	BumbleSort1(L);
	//L在前面已经声明了一次,故默认为L
	PrintList(L);

	printf("该链表倒置后:\n");
	L = ReverseList(L);
	PrintList(L);

	printf("输入你要交换的两个结点:");
	scanf("%d %d", &num1, &num2);
	L = swap(L, num1, num2);
	PrintList(L);

	printf("输入要在链表的前面插入的数据:");
	scanf("%d", &num1);
	L = addhead(L, num1);
	PrintList(L);

	printf("输入要插入的结点位置 数据:");
	scanf("%d %d", &num1, &num2);
	L = InsertNode(L, num1, num2);
	PrintList(L);

	printf("输入你要删除的数据:");
	scanf("%d", &num1);
	L = DeleteData(L, num1);
	PrintList(L);
	return 0;
}


  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值