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