【数据结构(ywm版)】异或指针双向链表
在《数据结构题集》中看到这种链表,实际上就是把一般的双向链表的next和prior两个指针通过异或运算合并为一个指针域来存储,每个结点确实可以减少一个指针的空间,但会带来取指针值时运算的开销。
实现的时候,先搞清双向链表,把握异或指针域的原理公式,然后从双向链表出发进行转换即可。
typedef struct XorNode{ //结点的定义
ElemType data;
struct XorNode* LRPtr;
}XorNode, *XorPointer; typedef struct{//无头结点的异或指针双向链表
XorPointer Left, Right; //只保存指向首、末结点的指针
}XorList;
每个结点的指针域存的是它的前驱和后继的异或值,即 LRPtr = prior ^ next,指针异或运算本质上就是整型的内存地址的按位异或。
//指针异或函数,注意指针变量不支持^运算,需要强转为整型(内存地址,长度与机器有关,C将之封装为size_t型)
XorPointer XorP(XorPointer p, XorPointer q){
size_t x = (size_t)p;
size_t y = (size_t)q;
return (XorPointer)(x^y);
}
这相当于把前驱和后继的指针编码到一个指针域中了,那么如何解码呢,只凭LRPtr本身是不可以的,必须再已知prior或next才行,这得益于异或运算特有的“对称”性质。
异或运算满足结合律,0为幺元,每个元素和自身互为逆元;所以设a, b为两个内存地址,则有
a^(a^b) = (a^a)^b = b;
(a^b)^b = a^(b^b) = a;
有了这两条,则可推出取得前驱或后继的式子,即
prior = LRPtr ^ next;
next = prior ^ LRPtr;
根据这两个关系,把双向链表的next和prior的运算用LRPtr替换即可。注意由于是循环链表,只有一个元素时,其前驱和后继都为自身。
注意我实现的是无头结点的循环链表,而链表的表长又不是显式维护的,所以要以回到起点作为循环退出条件之一,并设一个记录步数的变量k来避免 i 值超过表长而导致的“兜圈子”;在边界操作时注意修改首末元素指针。
Status CreateList(XorList& L, int n){
//头插法建表,无头结点,入口条件:n>=1
n--;
XorPointer p;
p = (XorPointer)malloc(sizeof(XorNode));
L.Left = L.Right = p;
p->data = n;
p->LRPtr = XorP(p, p);
while(n--){
p = (XorPointer)malloc(sizeof(XorNode));
p->data = n;
p->LRPtr = XorP(L.Right, L.Left);
L.Left->LRPtr = XorP(p, XorP(L.Right, L.Left->LRPtr));
L.Right->LRPtr = XorP(XorP(L.Right->LRPtr,L.Left),p);
L.Left = p;
}
} Status Insert(XorList& L, int i, ElemType e){
//在第i个位置前插入结点e(i的合法值为1~表长+1)
//由于无头结点,故判断表长是否够i,要通过计步变量k
XorPointer p = L.Left, q = L.Right;
int k = ;
while(p!=L.Right && k<i){ //p指向i, q指向i-1;保证至多扫描一遍后退出
XorPointer t = p;
p = XorP(q, p->LRPtr);
q = t;
k++;
}
if(k+<i) return ERROR; //表长不够i-1
if(k+==i){p = L.Left; q = L.Right;} //插到表长+1的位置,即最后一个元素之后
XorPointer s = (XorPointer)malloc(sizeof(XorNode));
s->data = e;
s->LRPtr = XorP(q, p);
q->LRPtr = XorP(XorP(q->LRPtr, p), s);
p->LRPtr = XorP(s, XorP(q, p->LRPtr));
if(i==) L.Left = s;
if(i==k+) L.Right = s;
return OK;
} Status Delete(XorList& L, int i, ElemType& e){
//删除第i个位置的元素,用e返回其值(i的合法值为1~表长)
XorPointer p = L.Left, q = L.Right;
int k = ;
while(p!=L.Right && k<i){ //p指向i, q指向i-1
XorPointer t = p;
p = XorP(q, p->LRPtr);
q = t;
k++;
}
if(k<i) return ERROR; //表长不够i
if(p==L.Right) L.Right = q; //删除最后一个结点
e = p->data;
XorPointer m = XorP(q, p->LRPtr); //m暂存p的后继
q->LRPtr = XorP(XorP(q->LRPtr, p), m);
m->LRPtr = XorP(q, XorP(p, m->LRPtr));
free(p);
if(i==) L.Left = m; //删除第一个结点
return OK;
} Status Traverse(XorList& L, void (*visit)(XorNode)){
XorPointer p = L.Left, q = L.Right;
while(p != L.Right){
visit(*p);
XorPointer t = p;
p = XorP(q,p->LRPtr);
q = t;
}
visit(*p);
return OK;
} void print(XorNode xn){
printf("[%d]",xn.data);
} int main()
{
XorList l;
CreateList(l,);
ElemType e;
if(Delete(l,,e))
Traverse(l,print);
return ;
}
【数据结构(ywm版)】异或指针双向链表的更多相关文章
- SDUT OJ 数据结构实验之链表九:双向链表
数据结构实验之链表九:双向链表 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descrip ...
- SDUT-2054_数据结构实验之链表九:双向链表
数据结构实验之链表九:双向链表 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 学会了单向链表,我们又多了一种解决问题的 ...
- 大话数据结构(八)Java程序——双向链表的实现
线性链表--双向链表 双向链表定义: 双向链表(double linked list): 是在单表单的每个结点中,再设置一个指向前驱结点的指针域.因此,在双向链表中的结点都有两个指针域,一个指向前驱, ...
- C和C指针小记(十八)-使用结构和指针-双向链表
1.双链表 1.1 双向链表的声明 在一个双链表中,每个节点都包含两个指针--指向前一个节点的指针和指向后一个节点的指针. 声明 typedef struct NODE { struct NODE * ...
- 数据结构复习之C语言指针与结构体
数据结构指针复习: #include <stdio.h> void main() { ] = {, , , , }; // a[3] == *(3+a) printf(+a)); // a ...
- 数据结构笔记1(c++)_指针
一.数据结构概述 1.定义: 我们如何把现实中大量而复杂的问题,以特定的数据类型和特定的存储结构保存到主存储器(内存)中,以及在此基础上为实现某个功能(比如查找某个元素,删除某个元素,对所有元素进行排 ...
- 数据结构C++版-队列
一.概念 分类: 二.补充说明 1.<面向对象的队列设计>课程问答: 首先要明确数据结构和数据存储结构的概念. 数据结构是指数据对象之间的逻辑关系,例如二叉树,队列,栈等,而数据存储结构是 ...
- cocos2dx解析lua table数据结构 简易版.
之前一直用xml填配置, cocos2dx自带了xml解析接口, 非常方便. 但是, 接口好用也改变不了xml的结构字符太多, 书写麻烦, 乱七八糟的事实. 很早就想换lua, 无奈引擎没有现成接口, ...
- 数据结构Java版之交换算法(一)
交换的本质是拷贝,其中拷贝包括两种方式.值拷贝和指针拷贝,在java中没有指针,为此,我们可以理解为地址拷贝,在我看来,指针就是地址. 1.传值方式示例: 由上述示例可得,传值,不能起到交换的作用,原 ...
随机推荐
- Linux下GDB调试C/C++
首先先编译程序并生成调试符号: gcc -g -c main.cpp gcc -o exefile main.o 以上的exefile为可执行程序的文件名 然后: gdb exefile 可以开始gd ...
- Clone Graph 解答
Question Clone an undirected graph. Each node in the graph contains a label and a list of its neighb ...
- Unique Binary Search Trees II 解答
Question Given n, generate all structurally unique BST's (binary search trees) that store values 1.. ...
- Impala 1、Impala理论
1.Impala简介 • Cloudera公司推出,提供对HDFS.Hbase数据的高性能.低延迟的交互式SQL查询功能. • 基于Hive使用内存计算,兼顾数据仓库.具有实时.批处理.多并发等优点 ...
- vue.js的devtools安装
安装 1.github下载地址:https://github.com/vuejs/vue-devtools 2.下载好后进入vue-devtools-master工程 执行npm install - ...
- MVC实用架构设计:总体设计
http://developer.51cto.com/art/201309/410166.htm
- Zjnu Stadium(hdu3047带权并查集)
题意:一个300列的无限行的循环场地,a b d代表a,b顺时针相距d的距离,现在给你一些距离,判断是否有冲突,如果有冲突计算冲突的次数 思路:带权并查集 a,b的距离等于b到根节点的距离 - a到根 ...
- stagefright框架(一)Video Playback的流程
在Android上,預設的多媒體框架(multimedia framework)是OpenCORE. OpenCORE的優點是兼顧了跨平台的移植性,而且已經過多方驗證,所以相對來說較為穩定:但是其缺點 ...
- React-Native ListView加载图片淡入淡出效果的组件
今天练习项目中需要给listview在加载图片时增加一个淡入淡出的效果,因此干脆就自己封装了一个组件: 'use strict' import React from 'react-native' va ...
- Failed to create the Java Virtual Machine (Myeclipse或者eclipse启动报错)
把某几个值改为原来的0.5倍就ok了(我就这么解决的) eclipse.ini如下: -startupplugins/org.eclipse.equinox.launcher_1.2.0.v2 ...