C++双向链表

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;  
}  

双向链表的遍历来说我只给出了前序遍历的代码,没有写后序遍历的代码,这其实是差不多的,但是因为双向链表可以进行两个方向的遍历,这给我们带来了很大的方便。

已标记关键词 清除标记
<p> <span style="color:#337FE5;"><strong>【为什么还需要学习C++?】</strong></span> </p> <p style="margin-left:0cm;"> 你是否接触很多语言,但从来没有了解过编程语言的本质? </p> <p style="margin-left:0cm;text-align:start;"> 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? </p> <p style="margin-left:0cm;text-align:start;"> 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹? </p> <p style="margin-left:0cm;text-align:start;">   </p> <p style="margin-left:0cm;text-align:start;"> 那么C++就是你个人能力提升,职业之路进阶的不二之选。 </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p style="margin-left:0cm;"> <strong><span style="color:#337FE5;">【课程特色】</span></strong> </p> <p style="margin-left:0cm;text-align:start;"> 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 </p> <p style="margin-left:0cm;text-align:start;"> 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 </p> <p style="margin-left:0cm;text-align:start;"> 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p class="ql-long-24357476"> <span style="color:#337FE5;"><strong>【学完后我将达到什么水平?】</strong></span> </p> <p class="ql-long-24357476"> 1.对C++的各个知识能够熟练配置、开发、部署; </p> <p class="ql-long-24357476"> 2.吊打一切关于C++的笔试面试题; </p> <p class="ql-long-24357476"> 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 </p> <p class="MsoNoSpacing" style="margin-left:18pt;"> <br /> </p> <div> <br /> </div> <p> <br /> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#337FE5;"><strong>【面向人群】</strong></span> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;">1.希望一站式快速入门的C++初学者;</span> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;">2.希望快速学习 C++、掌握编程要义、修炼内功的开发者;</span> </p> <p style="margin-left:0cm;text-align:start;"> <span style="color:#222226;font-family:PingFangSC-Regular, "font-size:14px;background-color:#FFFFFF;">3.有志于挑战更高级的开发项目,成为资深开发的工程师。</span> </p> <p style="margin-left:0cm;text-align:start;"> <br /> </p> <p> <br /> </p> <p> <span style="color:#337FE5;"><strong>【课程设计】</strong></span> </p> <p> 本课程包含3大模块 </p> <p> <strong>基础篇</strong><br /> 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 </p> <p> <br /> <strong>进阶篇</strong><br /> 本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 </p> <p> <br /> <strong>提升篇:</strong><br /> 本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。 </p> <p> <img src="https://img-bss.csdnimg.cn/202007091130239667.png" alt="" /> </p>
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页