数据结构之双向循环链表(C++实现)

下午上机的时候大概地实现了链表的基本功能。写的时候也不是光是脑袋想,

就在word里面画了个粗糙的图形,边看边写。刚刚开始的时候功能可以不要

太多。把最基本的功能先实现,也就是数据定义,default constructor和destructor的功能

。然后测试,再增加功能,这样后来写的时候出错的时候就会很明朗,至少不会是前面写的

function出错了。g++和vc下调试通过。main里面的测试只是其中的一部分,写的时候删了许多。

双向循环链表。首先它是一个环状的,只是不是那么圆,就像一个蛇咬住了自己的尾巴,那个发现苯环

的人就是晚上做了个梦,蛇咬住了自己的尾巴,然后他发现了苯环的结构。灵感源自生活,所以我们程序员

虽然总是对着电脑,但是请不要忘了,离开了电脑我们还有很广阔的世界,说多了哈,刚刚打了下酱油。

接着上面的。然后它又是双向的,所以它应该有2个指针,一个就是pre(前驱),一个就是next(后继)。

就像右边这个图里面画的那样,画的不咋样,这个还是到寝室后重新画的。

清楚了它的结构,实现起来就比较简单了,某些功能比单链表实现起来更简单点,毕竟它是双向的,所以很灵活,链表的用途还是很广泛的,os里面的各种作业调度算法的实现都是和链表息息相关。所以它的重要性可见一斑了。

如果你自己感兴趣的话也可以自己去实现一下,C/C++都行。

链表的学习到这里就结束了,对数据结构,linux C/C++有着浓厚兴趣的同学可以加群91926913一起交流下。

最后请看下面的代码。

转载请注明出处,谢谢!

dclink.h

 

#ifndef DCLINK_H
#define DCLINK_H
//双向循环链表
typedef int datatype;
//方便修改
//当然也可以写成模板来适应更多的数据类型
struct dclink{
	datatype data;//数据定义
	struct dclink *pre;
	struct dclink *next;//前驱和后继指针
};
class DCLink
{
public:
	DCLink();//default constructor
	DCLink(datatype data);//单参constructor
	void add(datatype data);//添加data到链表中去
	datatype getData(int pos)const;//获得指定位置的数据
	int deleteData(int pos);//删除指定位置的数据
	int modify(int pos, datatype data);//更改指定位置的数据
	int insert(int pos, datatype data);//在指定位置插入数据
	void sort()const;//循环链表排序
	int rePrint()const;//双向循环链表转置没啥意义,转置输出还有那么点意义
	int print()const;//打印链表
	~DCLink();//destructor
	int getLength()const;//得到链表的长度
private:
	DCLink operator=(const DCLink &dcl){}//assignment constructor 禁止
	DCLink (const DCLink &dcl){}//copy constructor 禁止
	struct dclink *head;//头指针
	struct dclink *cur;//当前指针
	int size;//大小
};
#endif


DCLink.cpp

#include "dclink.h"
#include <iostream>
//default constructor
DCLink::DCLink(){
	head = cur = NULL;//默认为空
	size = 0;
}
DCLink::DCLink(datatype data){//单参constructor
	head = new struct dclink[1];//申请空间
	cur = head;//指向当前节点
	head->data = data;
	head->next = head->pre = head;//指向自身
	size = 1;
}
void DCLink::add(datatype data){//添加data到链表中去
	//默认添加到表尾
	struct dclink *dcl = new struct dclink[1];
	dcl->data = data;
	if (NULL != head){//表非空
		//当前节点为第1号节点,它的后继节点为第2号节点
		struct dclink *temp = cur->next;//保持2号节点的位置
		cur->next = dcl;//1号节点的后继和新增节点相连
		dcl->pre = cur;//新增节点的前驱和1号节点相连
		dcl->next = temp;//新增节点的后继和2号节点相连
		temp->pre = dcl;//新增节点和2号节点的前驱相连
	}else {
		head = dcl;//新加节点成为头结点
		head->data = data;
		head->next = head->pre = head;//指向自身
	}//已经添加完毕,新增节点成为当前节点
	cur = dcl;
	size++;//长度+1
}
int DCLink::deleteData(int pos){//删除指定位置的数据
	if (size >= pos && pos > 0){//有数据并且没有越界才显示
		int count = 1;//计数
		struct dclink *temp = head;
		while (pos != count){
			temp = temp->next;//直到到达指定的位置
			count++;
		}//先到达指定位置
		//分情况是因为如果删除最后一个节点会改变cur的状态,挂空指针
		if (size == pos){
			if (1 == size){//只有一个节点的时候
				delete []temp;
				head = cur = NULL;//置空
				size--;//-1
				return 0;
			}else{//删除最后一个节点
				cur = temp->pre;//向前移动一个位置
			}
		}else{//如果删除第一个节点head会改变
			if (1 == pos){
				head = temp->next;//向后移动一个位置
			}
		}
		//当前节点为0号节点,后继节点为1号节点,前驱节点为-1号节点
		temp->pre->next = temp->next;//-1号节点的后继和1号节点相连
		temp->next = temp->pre;//1号节点的前驱和-1号节点相连
		size--;//长度-1
		return 0;//成功返回0
	}
	return -1;//无数据或者越界返回-1
}
int DCLink::modify(int pos, datatype data){//更改指定位置的数据
	if (size >= pos && pos > 0){//有数据并且没有越界才显示
		int count = 1;//计数
		struct dclink *temp = head;
		while (pos != count){
			temp = temp->next;
			count++;
		}
		temp->data = data;//更新
		return 0;
	}
	return -1;//无数据或者越界返回-1
}
int DCLink::insert(int pos, datatype data){//在指定位置插入数据
	if (0 == size && 1 == pos){
		this->add(data);//直接调用add函数
		return 0;
	}
	if (size >= pos && pos > 0){//有数据并且没有越界才显示
		int count = 1;//计数
		struct dclink *dcl = new struct dclink[1];
		dcl->data = data;
		struct dclink *temp = head;
		while (pos != count){
			temp = temp->next;//直到到达指定的位置
			count++;
		}//先到达指定位置
		//分情况是因为如果插入到第一个节点会改变head的状态
		if (size == pos){
			if (1 == size){//只有一个节点的时候
				head = dcl;//当前结点成为头结点
				head->next = temp;//新结点的后继和旧头结点相连
				temp->pre = head;//旧头结点的前驱和新结点相连
				head->pre = temp;//新结点的前驱和旧头结点相连
				temp->next = head;//旧头结点的后继和新结点相连
			}else{//插入到尾结点的前面
				temp->pre->next = dcl;
				dcl->pre = temp->pre;
				dcl->next = temp;
				temp->pre = dcl;
			}
			size++;
			return 0;
		}else{
			if (1 == pos){//插入到第一个位置
				head = dcl;//当前结点成为头结点
				head->next = temp;//新结点的后继和旧头结点相连
				temp->pre = head;//旧头结点的前驱和新结点相连
				head->pre = temp->pre;//新结点的前驱和旧头结点相连
				temp->pre->pre = head;//旧头结点的后继和新结点相连
			}else {//插入到中间的其它位置
				temp->pre->next = dcl;
				dcl->pre = temp->pre;
				dcl->next = temp;
				temp->pre = dcl;
			}
			size++;
			return 0;
		}
	}
	return -1;//越界返回-1
}
datatype DCLink::getData(int pos)const{//获得指定位置的数据
	if (size >= pos && pos > 0){//有数据并且没有越界才显示
		int count = 1;//计数
		struct dclink *temp = head;
		while (pos != count){
			temp = temp->next;//比插入和删除简单很多
			count++;//+1,第一次写的时候忘了+1,然后就固执地认为getData肯定没问题
			//可bug就在这里
		}
		return temp->data;
	}
	return -1;//无数据或者越界返回-1
}
void DCLink::sort()const{//排序
	if (1 < size){
		//快速排序
		int i = 1;
		int j = 0;
		struct dclink *ohead = head;
		while (size != i){//循环size - 1次
			j = 0;//重置
			struct dclink *temp = ohead;//辅助指针
			while (j != size - i){
				if (ohead->data > temp->next->data){//交换排序
					ohead->data += temp->next->data;
					temp->next->data = ohead->data - temp->next->data;
					ohead->data -= temp->next->data;
				}
				temp = temp->next;//移动
				j++;
			}
			ohead = ohead->next;//前面j个数据已经排好
			i++;
		}
	}
}
int DCLink::rePrint()const{//打印链表
	if (NULL != head){//链表非空
		struct dclink *temp = head;
		int count = 0;//计数
		while (size != count){
			temp = temp->pre;
			std::cout<<temp->data<<std::endl;
			count++;
		}
		return 0;
	}
	return -1;//空表返回-1
}
int DCLink::print()const{//打印链表
	if (NULL != head){//链表非空
		struct dclink *temp = head;
		int count = 0;//计数
		while (size != count){
			std::cout<<temp->data<<"  ";
			temp = temp->next;
			count++;
		}
		return 0;
	}
	return -1;//空表返回-1
}
int DCLink::getLength()const{
	return size;
}//得到链表的长度
//destructor
DCLink::~DCLink()
{
	while (0 != size){//用size来控制析构的次数
		struct dclink *temp = head;//辅助指针
		head->pre->next = head->next;//让head的前一个节点指向它的后一个节点
		head = head->next;//head后移动一个节点
		head->pre = temp->pre;//head还是指向前一个节点
		delete []temp;
		size--;
	}
}

int main(void){
	DCLink dcl;
	for (int i = 100; i > 0; i--)
		dcl.add(i);
	dcl.print();
	std::cout<<std::endl;
	dcl.sort();
 	dcl.print();
	dcl.modify(1,10);
	dcl.modify(5,44);
	dcl.modify(3,33);
	dcl.deleteData(5);
	dcl.deleteData(1);
	dcl.deleteData(3);
	dcl.deleteData(6);
	dcl.add(5);
	for (i = 1; i < 7; i++)
		std::cout<<dcl.getData(i)<<std::endl;
	
	std::cout<<"the sizeof DCLink is "<<dcl.getLength()<<std::endl;
	dcl.print();

	return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章