C++双向链表
双向链表顾名思义就是每个结点具有两个指针,一个指向前一个结点,一个指向后一个结点,我们不必拘束与单链表的创建遍历操作等,这样大大减少了使用中存在的效率问题。
在单链表中,我们有一个数据域还有一个指针域,数据域用来存储相关数据,而指针域负责链表之间的“联系”,双向链表具有两个指针域,一个负责向后连接,一个负责向前连接。
//单链表结构
template<class T>
struct List{
T data;
struct List* next;
};
//双向链表结构
template<class T>
struct DNode{
public:
T value;
DNode *prev;
DNode *next;
};
同单链表一样,对双向链表的操作也有创建,插入,遍历,删除,销毁。
双向链表的创建
struct DNode{
public:
T value;
DNode *prev;
DNode *next;
public:
DNode(){
}
DNode(T t,DNode *prev,DNode *next){
this->value=t;
this->prev=prev;
this->next=next;
}
};
在创建双向链表的时候,我们需要初始化的有两个指针。同单链表一样,我们需要一个头指针来标志链表的信息。因此我们可以写出该函数的定义:运用构造函数创建双向链表
双向链表具体操作:
template<class T>
class DoubleCircleList{
public:
DoubleCircleList(); //构造函数 创建链表
~DoubleCircleList(); //析构函数 销毁链表
int size(); //长度
int is_empty();//判断是否为空
T get(int index); //返回index值的位置
T get_first();//返回第一个位置
T get_last();//返回最后一个位置
int insert(int index,T t);//在index位置后插入数值
int insert_first(T t);//在头插入
int append_last(T t);//在尾插入
int Delete(int index);//删除index值
int Delete_first();//删除头结点
int Delete_last();//删除尾结点
private:
int count;
DNode<T>* phead;
DNode<T>* get_node(int index);
};
1.计算链表的长度
template<class T>
DoubleCircleList<T>::DoubleCircleList():count(0){
//创建“表头 ,注意:表头没有存储数据!
phead=new DNode<T>();
phead->prev=phead->next=phead;
//设置链表计数为0
//cout=0;
}
2.销毁链表
//析构函数 销毁链表
template<class T>
DoubleCircleList<T>::~DoubleCircleList(){
DNode<T>* ptmp;
DNode<T>* pnode=phead->next;
while(pnode!=phead){ //一直循环往后找
ptmp=pnode; //
pnode=pnode->next;
delete ptmp;
}
delete phead;
phead=NULL;
}
3.计算结点的数目
//返回结点数目
template<class T>
int DoubleCircleList<T>::size(){
return count;
}
4.判断链表是否为空
template<class T>
int DoubleCircleList<T>::is_empty(){
return count==0;
}
5.寻找结点位置
template<class T>
DNode<T>* DoubleCircleList<T>::get_node(int index){
//判断参数有效性
if(index<0||index>=count){
cout<<"get node failed! the index in out of bound!"<<endl;
return NULL;
}
//正向查找
if(index<=count/2){
int i=0;
DNode<T>* pindex=phead->next;
while(i++<index){
pindex=pindex->next;
}
return pindex;
}
//反向查找
int j=0;
int rindex=count-index-1;
DNode<T>* prindex=phead->prev;
while(j++<rindex){
prindex=prindex->prev;
}
return prindex;
}
6.返回结点位置的值
template<class T>
T DoubleCircleList<T>::get(int index){
return get_node(index)->value;
}
7.获取第一个结点的值
template<class T>
T DoubleCircleList<T>::get_first(){
return get_node(0)->value;
}
8.获取最后一个结点的值
template<class T>
T DoubleCircleList<T>::get_last(){
return get_node(count-1)->value;
}
9.将结点插入index之后
template<class T>
int DoubleCircleList<T>::insert(int index,T t){
if(index==0)
return insert_first(t);
DNode<T>* pindex=get_node(index);
DNode<T>* pnode=new DNode<T>(t,pindex->prev,pindex);
pindex->prev->next=pnode;
pindex->prev=pnode;
count++;
return 0;
}
10.结点插入到第一个位置
//将结点插入到第一个结点处
template<class T>
int DoubleCircleList<T>::insert_first(T t){
DNode<T>* pnode=new DNode<T>(t,phead,phead->next);
phead->next->prev=pnode;
phead->next=pnode;
count++;
return 0;
}
11.结点插入到最后一个位置
template<class T>
int DoubleCircleList<T>::append_last(T t){
DNode<T>* pnode=new DNode<T>(t,phead->prev,phead);
phead->prev->next=pnode;
phead->prev=pnode;
count++;
return 0;
}
12.删除index结点.
template<class T>
int DoubleCircleList<T>::Delete(int index){
DNode<T>* pindex=get_node(index);
pindex->next->prev=pindex->prev;
pindex->prev->next=pindex->next;
delete pindex;
count--;
return 0;
}
13.删除第一个结点
template<class T>
int DoubleCircleList<T>::Delete_first(){
return Delete(0);
}
14.删除最后一个结点
template<class T>
int DoubleCircleList<T>::Delete_last(){
return Delete(count-1);
}
完整代码:
//DoubleCircleList.h
#include<iostream>
using namespace std;
template<class T>
struct DNode{
public:
T value;
DNode *prev;
DNode *next;
public:
DNode(){
}
DNode(T t,DNode *prev,DNode *next){
this->value=t;
this->prev=prev;
this->next=next;
}
};
template<class T>
class DoubleCircleList{
public:
DoubleCircleList(); //构造函数 创建链表
~DoubleCircleList(); //析构函数 销毁链表
int size(); //长度
int is_empty();//判断是否为空
T get(int index); //返回index值的位置
T get_first();//返回第一个位置
T get_last();//返回最后一个位置
int insert(int index,T t);//在index位置后插入数值
int insert_first(T t);//在头插入
int append_last(T t);//在尾插入
int Delete(int index);//删除index值
int Delete_first();//删除头结点
int Delete_last();//删除尾结点
private:
int count;
DNode<T>* phead;
DNode<T>* get_node(int index);
};
template<class T>
DoubleCircleList<T>::DoubleCircleList():count(0){
//创建“表头 ,注意:表头没有存储数据!
phead=new DNode<T>();
phead->prev=phead->next=phead;
//设置链表计数为0
//cout=0;
}
//析构函数
template<class T>
DoubleCircleList<T>::~DoubleCircleList(){
DNode<T>* ptmp;
DNode<T>* pnode=phead->next;
while(pnode!=phead){ //一直循环往后找
ptmp=pnode; //
pnode=pnode->next;
delete ptmp;
}
delete phead;
phead=NULL;
}
//返回结点数目
template<class T>
int DoubleCircleList<T>::size(){
return count;
}
template<class T>
int DoubleCircleList<T>::is_empty(){
return count==0;
}
template<class T>
DNode<T>* DoubleCircleList<T>::get_node(int index){
//判断参数有效性
if(index<0||index>=count){
cout<<"get node failed! the index in out of bound!"<<endl;
return NULL;
}
//正向查找
if(index<=count/2){
int i=0;
DNode<T>* pindex=phead->next;
while(i++<index){
pindex=pindex->next;
}
return pindex;
}
//反向查找
int j=0;
int rindex=count-index-1;
DNode<T>* prindex=phead->prev;
while(j++<rindex){
prindex=prindex->prev;
}
return prindex;
}
template<class T>
T DoubleCircleList<T>::get(int index){
return get_node(index)->value;
}
//获取第1个结点值
template<class T>
T DoubleCircleList<T>::get_first(){
return get_node(0)->value;
}
//获取最后一个结点值
template<class T>
T DoubleCircleList<T>::get_last(){
return get_node(count-1)->value;
}
//将结点插入到index位置之前
template<class T>
int DoubleCircleList<T>::insert(int index,T t){
if(index==0)
return insert_first(t);
DNode<T>* pindex=get_node(index);
DNode<T>* pnode=new DNode<T>(t,pindex->prev,pindex);
pindex->prev->next=pnode;
pindex->prev=pnode;
count++;
return 0;
}
//将结点插入到第一个结点处
template<class T>
int DoubleCircleList<T>::insert_first(T t){
DNode<T>* pnode=new DNode<T>(t,phead,phead->next);
phead->next->prev=pnode;
phead->next=pnode;
count++;
return 0;
}
//结点追加到链表末尾
template<class T>
int DoubleCircleList<T>::append_last(T t){
DNode<T>* pnode=new DNode<T>(t,phead->prev,phead);
phead->prev->next=pnode;
phead->prev=pnode;
count++;
return 0;
}
//删除index位置结点
template<class T>
int DoubleCircleList<T>::Delete(int index){
DNode<T>* pindex=get_node(index);
pindex->next->prev=pindex->prev;
pindex->prev->next=pindex->next;
delete pindex;
count--;
return 0;
}
//删除第一个结点
template<class T>
int DoubleCircleList<T>::Delete_first(){
return Delete(0);
}
//删除最后一个结点
template<class T>
int DoubleCircleList<T>::Delete_last(){
return Delete(count-1);
}
//DoubleCircleList.cpp
#include <iostream>
#include "DoubleCircleList.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
void int_test()
{
int iarr[4] = {10, 20, 30, 40};//定义一个数组
cout << "\n开始测试 int数据" << endl;
// 创建双向链表
DoubleCircleList<int>* pdlink = new DoubleCircleList<int>();
pdlink->insert(0, 20); // 将 20 插入到第一个位置
pdlink->append_last(10); // 将 10 追加到链表末尾
pdlink->insert_first(30); // 将 30 插入到第一个位置
// 双向链表是否为空
cout << "is_empty()=" << pdlink->is_empty() <<endl;
// 双向链表的大小
cout << "size()=" << pdlink->size() <<endl;
// 打印双向链表中的全部数据
int sz = pdlink->size();
for (int i=0; i<sz; i++)
cout << "pdlink("<<i<<")=" << pdlink->get(i) <<endl;
}
int main(int argc, char** argv) {
int_test();
return 0;
}
双向循环链表:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct DOUBLE_LIST
{
int data;
struct DOUBLE_LIST *prev;
struct DOUBLE_LIST *next;
}double_list;
double_list *createlist() //创建有n个元素的双向链表 并输入元素
{
double_list *head, *p, *q;
int n,x;
head = (double_list *)malloc(sizeof(double_list));
head->prev = head;
head->next = head;
p = head;
printf("输入要创建双向链表的元素的个数:\n");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d", &x);
q = (double_list *)malloc(sizeof(double_list));
q->data = x;
p->next = q;
head->prev = q;
q->prev = p;
q->next = head;
p = q;
}
return head;
}
//遍历并且输出这些元素
void printlist(double_list *head)
{
double_list *p;
p = head;
p = p->next;
while(p!=head)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//得到现在双向链表中的元素的个数
int lengthlist(double_list *head)
{
double_list *p;
p = head;
p = p->next;
int coun = 0;
while(p!=head)
{
coun++;
p = p->next;
}
return coun;
}
//在第i个元素之前插入数据data
void insertlist_f(double_list *head, int i, int data)
{
double_list *p = head, *q;
p = p->next;
i--;
while(i--)
p = p->next;
q = (double_list *)malloc(sizeof(double_list));
q->data = data;
(p->prev)->next = q;
q->prev = p->prev;
q->next = p;
p->prev = q;
}
//删除第i个位置的元素
void deletelist_i(double_list *head, int i)
{
double_list *p = head;
p = p->next;
i--;
while(i--)
p = p->next;
(p->prev)->next = p->next;
(p->next)->prev = p->prev;
free(p);
}
//删除值为x的元素
void deletelist_x(double_list *head, int x)
{
double_list *p = head, *q;
p = p->next;
while(p!=head)
if(p->data == x)
{
q = p->next;
(p->prev)->next = p->next;
(p->next)->prev = p->prev;
free(p);
p = q;
}
else
p = p->next;
}
//对双向链表进行排序
void sortlist(double_list *head) //升序
{
double_list *p = head, *q, *t;
p = p->next;
for(;p!=head;p=p->next)
for(t = p->next;t!=head;t=t->next)
{
if(p->data > t->data)
{
int a = p->data;
p->data = t->data;
t->data = a;
}
}
}
int main()
{
double_list *head;
head = createlist();
deletelist_x(head, 2);
//sortlist(head);
printlist(head);
insertlist_f(head, 2, 2);
printlist(head);
return 0;
}
双向链表的遍历来说我只给出了前序遍历的代码,没有写后序遍历的代码,这其实是差不多的,但是因为双向链表可以进行两个方向的遍历,这给我们带来了很大的方便。