Program work 6. 每个节点只含一个链接点的双向链表实现

一般我们要实现双链表的时候,每个节点都会存一个数据元,然后一个左链接,然后一个右链接,以这种方式构造出一个双向链.

这里要分享的一个想法,每个节点都只会存一个数据元,然后仅有一个链接,以这种方式构造一个双向链表.

具体方式如下:

  关键在两点,异或运算,和地址.

  所以说每个节点里面存放的是什么呢?不是地址,而是两个相邻元素的地址异或运算后得到的结果.(有点抽象)

        我们假设: A节点地址为1000, B节点地址为1101, C节点的地址为1010. 所以B节点的link存的是:1000异或1010的结果---即:0010. 

                          当B节点想访问C节点时, 我们只要获取A节点的地址, 然后与B的link进行异或, 然后就可以得到节点C的地址, 进而访问节点C. 

                          由于异或运算的等价性, 如果我们从B节点访问A节点时, 也是只要获得右邻节点C的地址值, 然后同样与B的link进行异或, 就可以获得节点A的地址, 进而访问节点A.

        从上述描述方法中, 可以看到, 我们再做链表遍历无论是哪个方向, 都需要两个节点进行辅助, 一个节点记录当前节点, 一个记录前节点. 特别地如果你有特殊需求可能一会访问左一会访问右的话, 就需要3个节点了. 其中外围两个节点是记录了各自方向的前节点.

        还需要额外两个节点记录链表的两头, 然后两头节点的两边还有两个"隐形"地址, 为0x0, 当第二个节点进来的时候, 就用0x0与该节点地址异或运算, 然后付给第一个节点的link, 这是本人实现的具体细节, 各自也可根据情况自定. 


Program environment:

      Operation System: Ubuntu 14.04, 

      Ide: Eclipse, 

      Compiler: g++;

      Language: c++

Requirements & Method:

From the problem description, we know that the following requirements:

      A. Implement a double link list using link list data strucuture with just a link pointer.

      B. To achieve the A, using a special technique: xor operation.

Specifically:

1. Initial the first node’s link to the address 0x00 as its previous node’s address.

2. For each new node insertion, get the address of the new node a_c, and get the address of the node before the previous node a_p. Thus, the previous node’s link can be calculated with a_p ^ a_c.

3. The current node’s link point to the previous node’s address.

    The method of traversal has already stated clearly in the description, and won’t be repeated here.

Input & Output:

      Input:

            N integer, n is casual. To end the input, just enter -1, then [return].

      Output:

            Print out the double link list from left to right, and then right to left, or from right to left then from left to right. Either is OK, depending on your choice. 

//============================================================================
// Name        : Program.cpp
// Author      : Reid Chan
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <string>
#include <cctype>

using namespace std;

long add_p, add_c, add_n;

struct Node {
	int data;
	Node *link;
};

/**
 * @param start:
 * 			the start pointer of the traversal
 * @param end:
 * 			the end pointer of the traversal
 * @param msg:
 * 			msg can only be "address" or "link" for print out
 */
void print_out(Node *start, Node *end, string msg)
{
	Node *travel = start;
	add_p = (long)0x0;
	add_c = (long)travel;
	while (true) {
		cout << "data = " << travel->data << ", ";
		if (msg == "address") {
			cout << msg + " = " << travel << endl;
		} else {
			cout << msg + " = " << travel->link << endl;
		}
		if (travel == end) {
			break;
		}
		add_c = (long)travel;
		add_n = add_p ^ (long)travel->link;
		travel = (Node *)add_n;
		add_p = add_c;
	}
}

int main() {
	int data;
	Node *left, *right;		// left(right) node to record the left(right)-most of the link
	Node *prev, *curr;		// prev to record the previous node, curr to record the current node

	/*** Initial the first node of the link ***/
	cout << "Input (-1 to end input): ";
	cin >> data;
	prev = new Node;
	prev->data = data;
	prev->link = (Node *)0x0;
	left = prev;

	/*** create the link ***/
	while (cin >> data && data != -1) {
		curr = new Node;
		curr->data = data;						// insert a new node store in curr node
		add_p = (long)prev->link;				// get the address of the previous node of previous node
		add_c = (long)curr;						// get the address of the current node
		prev->link = (Node *)(add_p ^ add_c);	// the prev node link caculation
		curr->link = prev;						// the curr node link point to the prev nodee
		prev = curr;							// the curr node will be the prev node of next operation.
	}
	right = curr;

	cout << "Output: " << endl;
	print_out(left, right, "address");
	while (true) {
		cout << "Enter 1 to travel → then ←, enter 2 to travel ← then → ";
		int choice;
		cin >> choice;
		if (choice == 1) {
			cout << "From left to right: " << endl;
			print_out(left, right, "link");
			cout << "Then from right to left: " << endl;
			print_out(right, left, "link");
		} else {
			cout << "From right to left: " << endl;
			print_out(right, left, "link");
			cout << "Then from left to right: " << endl;
			print_out(left, right, "link");
		}
		char ans;
		cout << "Continue?(y/n): ";
		cin >> ans;
		if (tolower(ans) == 'n') {
			break;
		}
	}

 	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值