1.2.3 线性表 -双向链表

1 双向链表的定义

在双向链表的界定中有两个指针域,其一指向直接后继,另一个指向直接前驱。
在这里插入图片描述

typedef Node {
    datatype Data;
    struct Node *Prev;
    struct Node *Next;
}dlistnode, *dlinklist;

2 双向链表主要操作的实现

2.1 初始化一个空双向链表

dlinklist init_list(){
	// 申请一个头结点
	dlinklist head = calloc(1, sizeof(dlistnode)) ;
	if ( head!=NULL ){
		head->Prev = head->Next = head;
	}
	
	return head;
}

2.2 创建新节点new

dlinklist new_node(datatype data) {
	dlinklist new = calloc(1, sizeof(dlistnode));
	if ( new != NULL ){
		new->Data = data;
		new->Next = new;
		new->Prev = new;
	}
	return new;
}

2.3 双向链表结尾的插入

在这里插入图片描述

// 2.2 将新节点new插入到双向链表的末尾
void dll_add_tail(dlinklist new,dlinklist head){
	new->Prev = head->Prev;
	new->Next = head;
	head->Prev->Next = new;
	head->Prev = new;
}

2.4 双向链表结点的删除

在这里插入图片描述

 void del_node(dlinklist p) {
	// 删点 
	p->Next->Prev = p->Prev;
	p->Prev->Next = p->Next;
	// 删掉的点也让它不要乱指
	p->Next = p->Prev = p; 
}

2.6 双向链表的显示

void show_dll(dlinklist head) {
	dlinklist tmp = head->Next;
	while( tmp!= head){
		printf("%d\t", tmp->Data);
		tmp = tmp->Next;
	}
	printf("\n");
}

3 题目

用链表存储若干自然数。比如:
使得容器中存储: 1 2 3 4 5 6 7 8 9
要求将其重排成: 1 3 5 7 9 8 6 4 2 (即奇数升序偶数降序)

#include "common.h"

#ifndef DLL_NODE_TYPE
#define DLL_NODE_TYPE int
#endif

typedef DLL_NODE_TYPE datatype;

// 设计双向链表的结点
typedef struct node{
	datatype Data;
	struct node *Prev;
	struct node *Next;
}dlistnode, *dlinklist; 

// 1. 初始化一条空链表
dlinklist init_list(){
	// 申请一个头结点
	dlinklist head = calloc(1, sizeof(dlistnode)) ;
	if ( head!=NULL ){
		head->Prev = head->Next = head;
	}
	
	return head;
}

// 2.1 创建新节点new
dlinklist new_node(datatype data) {
	dlinklist new = calloc(1, sizeof(dlistnode));
	if ( new != NULL ){
		new->Data = data;
		new->Next = new;
		new->Prev = new;
	}
	return new;
}

// 2.2 将新节点new插入到链表的末尾
void dll_add_tail(dlinklist new,dlinklist head){
	new->Prev = head->Prev;
	new->Next = head;
	head->Prev->Next = new;
	head->Prev = new;
}

// 显示
void show_dll(dlinklist head) {
	dlinklist tmp = head->Next;
	while( tmp!= head){
		printf("%d\t", tmp->Data);
		tmp = tmp->Next;
	}
	printf("\n");
}

// 3.1 双向链表删除结点
void del_node(dlinklist p) {
	// 删点 
	p->Next->Prev = p->Prev;
	p->Prev->Next = p->Next;
	// 删掉的点也让它不要乱指
	p->Next = p->Prev = p; 
}

// 3.2 将偶数的移到后面,移动 = 删除+插入
void move_even_tail( dlinklist p, dlinklist head) {
	// 删除
	del_node(p) ;
	// 将结点添加到链表结尾
	dll_add_tail(p, head) ;
}

// 3 翻转
void rearrange(dlinklist head) {
	dlinklist p,k;
	for ( p=k=head->Prev; p!=head; p=p->Prev){
		if(p->Data % 2 == 0){
			// 偶数移动
			move_even_tail(p, head) ;
			p = k;
		} else{
			// 奇数 
			k = p;
		}
	}
}



int main(void){
	// 1. 初始化一条空链表
	dlinklist head = init_list();
	// 2. 循环地插入一些结点
	int n;
	scanf("%d", &n);
	
	int i;
	for ( i=1; i<=n;i++){
		// 创建新节点new
		dlinklist new = new_node(i);
		// 将新节点new插入到链表的末尾
		dll_add_tail(new, head);
	}
	// 显示 
	show_dll(head);
	// 3 奇偶数重排
	rearrange(head);
	show_dll(head);
//	// 4 销毁链表 
//	destroy(head);
}

代码引用常用头文件,如果报错可以参考另外一篇常用头文件 - common.h

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值