线性结构之双链表

一.引入

        在单链表的每个结点中再设置一个指向其前驱结点的指针域,这样就形成了双链表。其中,data 为数据域,存放数据元素;prior 为前驱指针域,存放该结点的前驱结点的地址;next 为后继指针域,存放该结点的后继结点的地址。



二.算法设计

DoubLinkedList.h

#ifndef SRC_DOUBLINKEDLIST_H_
#define SRC_DOUBLINKEDLIST_H_

template <class T>
struct Node{
	T data;
	Node<T> *prior;
	Node<T> *next;
};

template <class T>
class DoubLinkedList {
public:
	DoubLinkedList();
	DoubLinkedList(T array[],int length);
	virtual ~DoubLinkedList();
	int getLength();
	void getAll();
	T getByIndex(int index);
	void getByValue(T value);
	void insert(int index,T value);//把指针移到插入点的后面
	void add(T value);//在尾部添加元素
	void removeByIndex(int index);
	void removeByValue(T value);
	void updateByIndex(int index,T value);
	void updateByValue(T oldValue,T newValue);
private:
	Node<T> *first;//头结点,prior存储的是第一个节点的地址,next存储的是最后一个节点的地址
	Node<T> *sign;//记号指针,用于运行某些方法时移动
	int length;
	bool checkIndex(int index);//检查角标是否符合要求
	void moveSign(int index);//移动记号指针
	void resetSign();//重置记号指针,将其指向头结点
};

#endif

三.详细设计(C++)

DoubLinkedList.cpp

#include "DoubLinkedList.h"
#include <iostream>
using namespace std;

template <class T>
bool DoubLinkedList<T>::checkIndex(int index){
	if(index < 0){
		cout<<"角标不能小于0!"<<endl;
		return false;
	}else if(index >= length){
		cout<<"角标越界,当前长度为:"<<length<<"!"<<endl;
		return false;
	}
	return true;
}

template <class T>
void DoubLinkedList<T>::moveSign(int index){
	if(index >= length/2){
		sign = first->next;
		for(int i = length-1;i > index;i--){
			sign = sign->prior;
		}
	}else{
		sign = first->prior;
		for(int i = 0;i < index;i++){
			sign = sign->next;
		}
	}
}

template <class T>
void DoubLinkedList<T>::resetSign(){
	sign = first;
}

template <class T>
DoubLinkedList<T>::DoubLinkedList(){
	first = new Node<T>;
	first->prior = first;
	first->next = first;
	length = 0;
	sign = first;
}

template <class T>
DoubLinkedList<T>::DoubLinkedList(T array[],int length){
	first = new Node<T>;
	for(int i = 0;i < length;i++){
		if(i == 0){
			Node<T> *s = new Node<T>;
			s->prior = s;
			s->data = array[i];
			s->next = s;
			first->prior = s;
			first->next = s;
		}else{
			Node<T> *s = new Node<T>;
			s->prior = first->next;
			s->data = array[i];
			s->next = first->prior;
			first->prior->prior = s;
			first->next->next = s;
			first->next = s;
		}
	}
	this->length = length;
	sign = first;
}

template <class T>
DoubLinkedList<T>::~DoubLinkedList(){
	Node<T> *removeNode = first->prior;
	while(removeNode != first->next){
		removeNode = removeNode->next;
		removeByIndex(0);
	}
	delete removeNode;
	delete first;
}

template <class T>
int DoubLinkedList<T>::getLength(){
	return length;
}

template <class T>
void DoubLinkedList<T>::getAll(){
	Node<T> *p = first->prior;
	int index = 0;
	while(p != first->next){
		if(index == 0){
			cout<<"["<<p->data<<",";
		}else{
			cout<<p->data<<",";
		}
		index++;
		p = p->next;
	}
	cout<<p->data<<"]"<<endl;
}

template <class T>
T DoubLinkedList<T>::getByIndex(int index){
	if(!checkIndex(index)){
		return -1;
	}
	moveSign(index);
	T data = sign->data;
	resetSign();
	return data;
}

template <class T>
void DoubLinkedList<T>::getByValue(T value){
	Node<T> *p = first->prior;
	bool flag = false;
	int index = 0;
	while(p != first->next){
		if(p->data == value){
			cout<<"arr["<<index<<"]="<<p->data<<" ";
			flag = true;
		}
		p = p->next;
		index++;
	}
	if(p->data == value){
		cout<<"arr["<<index<<"]="<<p->data<<endl;
		flag = true;
	}
	if(!flag){
		cout<<"没有此值!"<<endl;
	}
}

template <class T>
void DoubLinkedList<T>::insert(int index,T value){
	if(!checkIndex(index)){
		return;
	}
	moveSign(index);
	Node<T> *insertNode = new Node<T>;
	insertNode->prior = sign->prior;
	insertNode->data = value;
	insertNode->next = sign;
	sign->prior->next = insertNode;
	sign->prior = insertNode;
	if(first->prior == insertNode->next && first->next == insertNode->prior){
		first->prior = insertNode;
	}
	resetSign();
	length++;
}

template <class T>
void DoubLinkedList<T>::add(T value){
	Node<T> *p = first->prior;
	Node<T> *insertNode = new Node<T>;
	insertNode->prior = p->prior;
	insertNode->data = value;
	insertNode->next = p;
	p->prior->next = insertNode;
	p->prior = insertNode;
	first->next = insertNode;
	length++;
}

template <class T>
void DoubLinkedList<T>::removeByIndex(int index){
	if(!checkIndex(index)){
		return;
	}
	moveSign(index);
	if(sign == first->prior){
		first->prior = sign->next;
	}else if(sign == first->next){
		first->next = sign->prior;
	}
	sign->prior->next = sign->next;
	sign->next->prior = sign->prior;
	Node<T> *removeNode = sign;
	delete removeNode;
	length--;
	resetSign();
}

template <class T>
void DoubLinkedList<T>::removeByValue(T value){
	Node<T> *p = first->prior;
	bool flag = false;
	int index = 0;
	while(p != first->next){
		if(p->data == value){
			removeByIndex(index);
			flag = true;
			p = p->next;
			continue;
		}
		p = p->next;
		index++;
	}
	if(p->data == value){
		removeByIndex(index);
		flag = true;
	}
	if(!flag){
		cout<<"没有此值!"<<endl;
	}
}

template <class T>
void DoubLinkedList<T>::updateByIndex(int index,T value){
	moveSign(index);
	sign->data = value;
	resetSign();
}

template <class T>
void DoubLinkedList<T>::updateByValue(T oldValue,T newValue){
	Node<T> *p = first->prior;
	bool flag = false;
	while(p != first->next){
		if(p->data == oldValue){
			p->data = newValue;
			flag = true;
		}
		p = p->next;
	}
	if(p->data == oldValue){
		p->data = newValue;
		flag = true;
	}
	if(!flag){
		cout<<"没有此值!"<<endl;
	}
}

四.测试

TestDoubLinkedList.cpp

#include "DoubLinkedList.h"
#include "DoubLinkedList.cpp"
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
	int arr[] = {1,2,3,4,5,4,3,2,1};
	cout<<"创建对象"<<endl;
	DoubLinkedList<int> doubLinkedList(arr,9);
	cout<<"对象长度:"<<doubLinkedList.getLength()<<endl;
	cout<<"遍历对象:";
	doubLinkedList.getAll();
	cout<<endl;

	cout<<"获取角标为6的元素:"<<doubLinkedList.getByIndex(6)<<endl;
	cout<<endl;

	cout<<"获取值为3的元素的角标:";
	doubLinkedList.getByValue(3);
	cout<<endl<<endl;

	cout<<"在角标为3的位置插入6:"<<endl;
	doubLinkedList.insert(3,6);
	cout<<"对象长度:"<<doubLinkedList.getLength()<<endl;
	cout<<"遍历对象:";
	doubLinkedList.getAll();
	cout<<endl;

	cout<<"移除角标为3的元素:"<<endl;
	doubLinkedList.removeByIndex(3);
	cout<<"对象长度:"<<doubLinkedList.getLength()<<endl;
	cout<<"遍历对象:";
	doubLinkedList.getAll();
	cout<<endl;

	cout<<"移除值为2的元素:"<<endl;
	doubLinkedList.removeByValue(2);
	cout<<"对象长度:"<<doubLinkedList.getLength()<<endl;
	cout<<"遍历对象:";
	doubLinkedList.getAll();
	cout<<endl;

	cout<<"把角标为5的元素的值修改为0:"<<endl;
	doubLinkedList.updateByIndex(5,0);
	cout<<"对象长度:"<<doubLinkedList.getLength()<<endl;
	cout<<"遍历对象:";
	doubLinkedList.getAll();
	cout<<endl;

	cout<<"把值为4的元素的值修改为8:"<<endl;
	doubLinkedList.updateByValue(4,8);
	cout<<"对象长度:"<<doubLinkedList.getLength()<<endl;
	cout<<"遍历对象:";
	doubLinkedList.getAll();
	cout<<endl;

	cout<<"销毁数组";
	doubLinkedList.~DoubLinkedList();
	cout<<endl;

	return 0;
}

五.运行结果



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值