DEV C++双链表的一些基本操作

创建空链表 求长度 输出 后插法创建链表 查找第i个元素 插入 查找某个值的位置
删除 链表冒泡排序 两个无序链表 合并为一个有序链表

/*
创建空链表 求长度 输出 后插法创建链表 查找第i个元素 插入 查找某个值的位置
删除 链表冒泡排序 两个无序链表合并为一个有序链表
*/

#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;  //Status是函数返回值类型,其值是函数结果状态代码
typedef int ElemType;  //ElemType为可定义的数据类型,此设为int类型

typedef struct DLNode {
	ElemType data;
	struct DLNode *prior;
	struct DLNode *next;
} DLNode, * DLinkList;

/**
  * @brief  构造一个带头结点空双向链表
  * @param  DLinkList类型
  * @retval 无
  */
Status DLinkList_Init(DLinkList &L) {
	L = new DLNode;
	L->prior = NULL;
	L->next = NULL;
	return OK;
}

/**
  * @brief  求双向链表长度,头结点除外
  * @param  DLinkList类型
  * @retval 长度int
  */
int DLinkList_Length(DLinkList L) {
	int len = 0;
	DLNode *p;
	p = L;
	if (!(p->next ))
		return 0;
	while (p = p->next )
		++len;
	return len;
}

/**
  * @brief  顺序输出双链表
  * @param  DLinkList类型
  * @retval 无
  */
void DLinkList_Output(DLinkList L) {
	DLNode *p;
	p = L;
	while (p = p->next )
		cout << p->data ;
	cout << endl;
}

/**
  * @brief  后插法,正序输入n个元素的值,建立带头结点的双向链表L
  * @param  DLinkList类型,元素个数n
  * @retval 无
  */
void DLinkList_Create(DLinkList &L, int n) {
	DLNode *p, *r;
	L = new DLNode;
	L->next = NULL;
	r = L;
	cout << "请输入" << n << "个数:\n";
	for (int i = 0; i < n; i++) {
		p = new DLNode;
		cin >> p->data ;
		p->next = NULL;
		r->next = p;
		p->prior  = r;
		r = p;
//		p->prior = L->prior ;
//		L->prior = p;
	}
	L->prior = NULL;
}
/*    书上是这样写的,我试了一下好像从后往前不太行
void DLinkList_Create(DLinkList &L, int n) {
	DLNode *p, *r;
	L = new DLNode;
	L->next = NULL;
	r = L;
	cout << "请输入" << n << "个数:\n";
	for (int i = 0; i < n; i++) {
		p = new DLNode;
		cin >> p->data ;
		p->next = NULL;
		r->next = p;
		r = p;
		p->prior = L->prior ;
		L->prior = p;
	}
}
*/

/**
  * @brief  双向链表查找第i个元素的指针
  * @param  DLinkList类型,位置i
  * @retval DLNode 类型
  */
DLNode *DLinkList_GetElem(DLinkList L, int i) {
	int j;
	DLNode *p;
	p = L->next ;
	j = 1;
	while (j < i && p) {
		p = p->next ;
		++j;
	}
	if (!p || j > i)
		return ERROR;
	return p;
}

/**
  * @brief  双向链表插入,i之前
  * @param  DLinkList类型,插入位置i,插入数据e
  * @retval 无
  */
Status DLinkList_Insert(DLinkList &L, int i, ElemType e) {
	DLNode *s, *p;
	if (i > (DLinkList_Length(L) + 1))
		return ERROR;
	if (i == 1 && (!L->next )) {//第一个位置插入
		p = new DLNode;
		p->data = e;
		L->next = p;
		p->prior = L;
		p->next = NULL;
		return OK;
	}
	if (i == (DLinkList_Length(L) + 1)) {//最后一个位置插入
		p = L;
		for (int t = 0; t < (i - 1); ++t)
			p = p->next ;
		s = new DLNode;
		s->data = e;
		s->prior = p;
		s->next = NULL;
		p->next = s;
		return OK;
	}
	p = L;
	for (int t = 0; t < i; ++t)
		p = p->next ;
	s = new DLNode;
	s->data = e;
	s->prior = p->prior ;
	p->prior ->next = s;
	s->next = p;
	p->prior = s;
	return OK;
}

/**
  * @brief  按值查找序号,当没有需要查找的值时,i=0
  * @param  LinkList类型,查找值,返回节点位置
  * @retval 该值对应的节点
  */
DLNode *DLinkList_LocateElem(DLinkList L, ElemType e, int &i) {
	i = 1;
	DLNode *p;
	p = L->next ;
	while (p && p->data != e) {
		++i;
		p = p->next ;
	}
	if (!p)
		i = 0;
	return p;
}

/**
  * @brief  双向链表删除第i个节点
  * @param  DLinkList类型,删除位置i
  * @retval 删除数据e
  */
Status DLinkList_Delete(DLinkList &L, int i) {
	int e;
	DLNode *p;
	if (!(p = DLinkList_GetElem(L, i)))
		return ERROR;
	e = p->data ;
	p->prior ->next = p->next ;
	p->next ->prior = p->prior ;
	delete p;
	return e;
}

/**
  * @brief  数组冒泡排序,升序
  * @param  数组类型,长度
  * @retval 无
  */
void Array_Maopao(ElemType array[], int n) {
	int i;  //比较的轮数
	int j;  //每轮比较的次数
	int buf;  //交换数据时用于存放中间数据
	for (i = 0; i < n - 1; ++i) { //比较n-1轮
		for (j = 0; j < n - 1 - i; ++j) { //每轮比较n-1-i次,
			if (array [j] > array [j + 1]) {
				buf = array [j];
				array [j] = array[j + 1];
				array [j + 1] = buf;
			}
		}
	}

}

/**
  * @brief  双链表冒泡排序,升序
  * @param  DLinkList类型
  * @retval 无
  */
void DLinkList_Maopao(DLinkList &a) {
	int n, flag = 0;
	DLNode *p;
	p = a ;
	n = DLinkList_Length(a);
	ElemType array[n];
	while (p = p->next ) {//把链表的值放到数组里,排序后再重新赋值
		array[flag] = p->data ;
		flag++;
	}
	Array_Maopao(array, n);
	p = a ;
	flag = 0;
	while (p = p->next ) {
		p->data = array[flag];
		flag++;
	}
	free(array);
}

/**
  * @brief  把无序双链表A和B合并到C中,不去重,升序
  * @param  DLinkList类型,DLinkList类型,DLinkList类型
  * @retval 无
  */
void DLinkList_Union_Orderly(DLinkList A, DLinkList B, DLinkList &C) {
	int n, flag = 0, flaga = 0, flagb = 0;
	int a_len, b_len;
	if (C->next ) {
		cout << "目标链表非空,原链表为:" ;
		DLinkList_Output(C);
	}
	ElemType temp;//临时存放当前节点数据
	DLNode *pa, *pb, *pc;
	pa = A ;
	pb = B;
	a_len = DLinkList_Length(A);
	b_len = DLinkList_Length(B);
	/***********************************************/
	ElemType array_a[a_len];//把值放到数组里,进行排序,而不影响原链表顺序
	ElemType array_b[b_len];
	while (pa = pa->next ) {
		array_a[flag] = pa->data ;
		++flag;
	}
	Array_Maopao(array_a, flag );
	flag = 0;
	while (pb = pb->next ) {
		array_b[flag] = pb->data ;
		++flag;
	}
	Array_Maopao(array_b, flag );
	/***********************************************/
	flag = DLinkList_Length(C) + 1; //以下作链表C的插入位置
	while (flaga < a_len && flagb < b_len) {
		if (array_a[flaga] < array_b[flagb]) {
			temp = array_a[flaga++];
			DLinkList_Insert(C, flag++, temp);
		} else {
			temp = array_b[flagb++];
			DLinkList_Insert(C, flag++, temp);
		}
	}
	while (flaga < a_len) {
		temp = array_a[flaga++];
		DLinkList_Insert(C, flag++, temp);
	}
	while (flagb < b_len) {
		temp = array_b[flagb++];
		DLinkList_Insert(C, flag++, temp);
	}
//	free(array_a);//如果free的话会错误,不知道为啥
//	free(array_b);
}

/****另一种写法,但还是不能释放数组的内存****/
//DLNode *DLinkList_Union_Orderly(DLinkList A, DLinkList B) {
//	int n, flag = 0, flaga = 0, flagb = 0;
//	int a_len, b_len;
//	DLinkList C;
//	DLinkList_Init(C);
//	ElemType temp;//临时存放当前节点数据
//	DLNode *pa, *pb, *pc;
//	pa = A ;
//	pb = B;
//	a_len = DLinkList_Length(A);
//	b_len = DLinkList_Length(B);
//	/***********************************************/
//	ElemType array_a[a_len];//把值放到数组里,进行排序,而不影响原链表顺序
//	ElemType array_b[b_len];
//	while (pa = pa->next ) {
//		array_a[flag] = pa->data ;
//		++flag;
//	}
//	Array_Maopao(array_a, flag );
//	flag = 0;
//	while (pb = pb->next ) {
//		array_b[flag] = pb->data ;
//		++flag;
//	}
//	Array_Maopao(array_b, flag );
//	/***********************************************/
//	flag = 1;//以下作链表C的插入位置
//	while (flaga < a_len && flagb < b_len) {
//		if (array_a[flaga] < array_b[flagb]) {
//			temp = array_a[flaga++];
//			DLinkList_Insert(C, flag++, temp);
//		} else {
//			temp = array_b[flagb++];
//			DLinkList_Insert(C, flag++, temp);
//		}
//	}
//	while (flaga < a_len) {
//		temp = array_a[flaga++];
//		DLinkList_Insert(C, flag++, temp);
//	}
//	while (flagb < b_len) {
//		temp = array_b[flagb++];
//		DLinkList_Insert(C, flag++, temp);
//	}
//	return C;
	free(array_a);如果先free在return的话会错误,不知道为啥
	free(array_b);
//}




+ 逆置

/**
  * @brief  双链表的逆置
  * @param  DLinkList类型
  * @retval 无
  */
Status DLinkList_Reverse(DLinkList &L) {
	DLNode *p, *r, *q;
	p = L;
	if (!(p = p->next )) {
		cout << "该链表为空" << endl;
		return ERROR;
	}
	int len = DLinkList_Length(L);
	while (--len) {
		p = p->next ;
	}
	len = DLinkList_Length(L);
	r = L;
	r->next = NULL;
	while (len--) {
		q = p;
		p = p->prior ;
		q->next = r->next ;
		q->prior = r;
		r->next = q;
		r = r->next ;
	}
	cout << "逆置后的链表为:";
	DLinkList_Output(L);
	return OK;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值