数据结构_线性表(线性表,单向链表,静态链表,循环链表,双向链表)

顺序表

  • 数组实现,存储空间是连续的
  • 随机存取,查找随机,增删要整体移动

定义

顺序表定义的三个要素

  • 底层数组的首地址
  • 存储空间的最大值(一开始就定了)
    *数组的长度(随机变化的)
#define MAXSIZE  100;
typedef struct {
	Elemtype  *  elem; //存储空间的地址
	int length; //当前的长度
}SqList;

初始化

为顺序表动态分配一个预定义大小的存储空间,使elem指向该存储空间
将表长置零

status InitList(SqList &L)
{
	L.elem = new Elemtype[MAXSIZE];
	if (L.elem == NULL)
	{
		return  ERROR; //存储空间申请失败
	}
	L.length = 0;
	return OK;
}

取值

  • 根据指定的位置,取得表中的值
  • 判断给定的位置是否合法
  • 将取出的值获取
status GetElem(SqList L, int i, Elemtype & e)
{
	if (i < 1 && i > L.length)
	{
		return ERROR;
	}
	e = L.elem[i - 1];
	return OK;
}

插入

  • 根据指定位置,插入一个元素
  • 判断插入位置是否合法,不合法就抛出异常
  • 判断表是否已经存满,存满就抛出异常
  • 从最后一个元素开始遍历到指定位置,依次向后移动一个位置
  • 将指定元素插入到指定位置
  • 表长 +1
Status InsertList(SqList &L,int i , ElemType e)
{	if(i < 1 && i > L.length) 
		return ERROR;
	if((L.length == MAXSIZE)
		return ERROR;
	for( int j = L.length-1; j >= i -1; j--)
	{	L.elem[j+1]  = L.elem[j];
	}
	elem[i-1] = e;
	L.length++;
	return OK;
}

删除

  • 判断删除位置是否合法
  • 把删除位置后的元素依次向前移动一位
  • 表长-1
status DeleteList(SqList &L, int i )
{	if( i < 1 && i > L.length)
		return ERROR;
	for(int j = i -1 ; j < length; j++)
	{	L.elem[j] = L.elem[j+1];
	}
	L.length --;
	return OK;
}

查找

  • 循环表,依次匹配要查找的元素
  • 找到就返回位置+1
  • 找不到就返回
Status LocateList(SqList &L, ElemType e)
{	for( int i = 0 ; i < L.length; i++)
	{	if(e == L.elem[i]) 
			return i + 1;
	}
	return  0 ;
}

单链表

  • 底层是链表实现的,存储空间可以不连续
  • 增删快,查改难,只能在表头进行查询

定义

  • 链表名是头指针,指向头结点
  • 头结点管理链表,指针域指向首元结点
  • 结点有两个域,数据域以及指针域
  • 先定义一个头结点,赋值给头指针
  • 头结点的指针域置为NULL
 typedef struct LNode {
   ElemType  data ;
   struct LNode * next ;
   } LNode  , * LinkList
		

初始化

  • 创建一个头结点,将指针赋值给头指针
  • 将头结点的指针域置为NULL
status InitList (LinkList &L)
{	
	L = new LNode;
	L-next = NULL;
	return OK;
}
	

前插入法创建单链表

  • 创建一个空链表
  • 根据指定的元素个数进行结点前插
  • 创建一个新的结点,对结点的数据域赋值,将结点插入到头结点后
status InitList_head(LinkList & L ,int i )
{	L = new LNode;
	L->next = NULL;
	for(int j = 1; j <= i; j++) 
	{	LNode * p  = new LNode();
		cin >> p -> data;
		p ->next = L->next; //新的结点指向首元结点
		L->next = p;	//头结点指向新的新的结点,新结点成为首元结点
	}
	
	return OK;
}

后插入法创建新链表

  • 创建一个空链表
  • 创建一个尾指针指向头结点
  • 根据指定的元素个数进行结点后插
  • 创建一个新的结点,对结点的数据域赋值,将结点拼接到末结点
status InitList_end(LinkList &L ,int i)
{	L = new LNode;
	L->next = NULL;
	LNode * r;
	r = L; 
	for( int j = 1; j < = i; j++)
	{	LNode * p = new LNode;
		cin >> p->data;
		p ->next = NULL;
		r ->next = p; //将p插入到位置
		r = p;  //将指针重新指向最后一个结点
	}
	return OK;
}
	

插入元素

  • 在指定位置i 插入一个新的结点
  • 创建一个新的结点指针p,初始化为头指针
  • 创建一个新的结点s,结点的指针域赋值为指定值
  • 创建一个计数器;
  • 从表头遍历链表,找到了指定位置,将结点a的指针赋值给结点指针p
  • 将 结点s指针域指向 结点 b ,再将结点a的指针域指向结点s
status InsertList(LinkList &L,int i, ElemType e)
{	
	LNode * p ;
	p = L;
	int j = 0;  //计数器
	while( p && j < i - 1)
	{	p = p ->next;
		j++;
	}
	if !p && j > i -1 ) 
		return ERROR;    //指定位置非法, i < 1  ||  i > n + 1 (为链表的元素个数)
	LNode * s = new LNode;
	s -> data = e;
	s -> next = p ->next;
	p -> next = s;
	return OK;
} 

取值

  • 获取指定位置的元素
  • 创建一个结点指针p,指向首元结点
  • 创建一个计数器,初始化为1
  • 遍历链表,查找指定的结点,循环条件(p不为NULL && j < i) ,循环体(p指向下一个指针,计数器加1)
  • 如果指针为空或者指定位置不合法(i <1 | | i > n),查找失败,返回ERROR
  • 查找成功则返回该元素
Status GetElem(LinkList lL, int i, ElemType &e)
{
	LNode * p = L -> next;
	int j = 1;
	while( p && j < i)
	{	p = p -> next;
		j++;
	}
	if( !p || j > i)
		return ERROR;
	e = p -> data;
	return OK;
}

查找

  • 判断指定元素是否存在,存在泽返回它的地址,否则返回NULL
  • 创建一个新的结点指针指向首元结点
  • 遍历链表,查找元素,循环条件为(p 不为NULL && p->data != 要查找的元素)
  • 返回当前的指针值,成功则返回指定元素的地址,失败则返回NULL
LNode * LocateList(LinkList L , ElemType e)
{	LNode * p = L->next;
	while( p && p ->data != e)
	{	p = p->next;
	}
	return p;
}

删除

  • 根据指定的位置删除元素
  • 创建结点指针p,初始化为头指针
  • 遍历链表,指针p获取指定位置的前一个结点的指针,循环条件为(当前指针所指结点的指针域不为零 && 当前位置小与指定位置的前一个结点)
  • 如果指定位置不合法则返回ERROR
  • 找到指定位置结点,保存该结点的指针,以备释放
  • 将指定位置前一个结点的指针域指向所找元素的下一个结点
  • 释放被删除的结点的资源
Status DeleteList(LinkList &L, int i )
{	pNode * p = L;
	int j = 0;
	while ( (p -> next) && (j < i - 1) )
	{	p  = p -> next;
		j++;
	}
	if( (p -> next) || j > i -1)  //  i <  1 || i  > n
		return ERROR;
	LNode * q = p ->next; //获取要删除的元素的地址
	p -> next = p ->next -> next;
	delete q;
	return OK;
}
	

单链表小项目练习

#pragma once
#include<iostream>
using namespace std;
#define OK 1;
#define ERROR 0;
//单链表的结点
typedef struct LNode  
{
	int data;
	struct LNode * next; //结点的指针域
}LNode, *Linklist;  // Linklist为指向结构体LNode的指针类型 ,定义数据类型

//单链表的初始化
/*
分析:
1,生成新节点作为头结点,用头指针L指向头结点
2,头结点的指针域置空
*/

bool InitList(Linklist &L)
{
	L = new LNode;		//1
	L->next = NULL;		//2
	return OK;
}

//单链表的取值
/*
分析:
1,用指p指向首元结点,用j做计数器初始值赋为1
2,从首元结点开始依次向下访问,只要指向当前结点的指针域不为空,并且没有到达要寻找序号为i的结点,则循环继续执行操作:
(1)p指向下一个结点;
(2)计数器j加一
(3)退出循环时,如果指针p为空,或者计数器大于i,说明指定的序号i不合法,取值失败返回ERROR
	若取值成功,此时j = i 时,p所指向的结点就时要找的第i个结点,用参数e 保存当前结点的数据域
	返回OK

*/
//根据序号i,再链表中寻找元素的值,用e获取该元素的值
bool GetElem(Linklist L, int i, int &e) {
	Linklist p = L->next;
	int j = 1; //计数器
	while (p && j < i)  //循环停止条件:p为空或者指向第i个元素
	{
		p = p->next;
		j++;
	}
	if (!p || j > i) //i值不合法
	{
		return ERROR; 
	}
	e = p->data; //e接收i结点的数据域
	return  OK; 
}

//根据相应元素查找
/*
分析:
1,用指针p指向首元结点
2,顺序查找,只要指向当前的指针p不为空,并且p所指结点的数据与不等于给定值,p就指向下一结点
3,返回p,若查找成功,返回该结点的地址值,若失败则返回NULL
*/

//再带有头结点的单链表中查询值为e的元素
LNode * LocateElem(Linklist L, int e) {
	LNode * p;
	p = L->next; // p指向首元结点
	while (p && p->data != e)
	{
		p = p->next;
	}
	return p;
}

//单链表插入元素
/*
分析:
1,查找结点a,并由指针p指向该结点
2,生成一个新的结点变量*s
3,将结点变量*s的数据域置为e,
4,将新结点的指针与指向第i+1个结点
5,将结点变量*p的指针域指向新结点变量*s*/

//在带有头结点的单链表L第i个位置插入值为e的新结点
bool ListInsert(Linklist &L, int i, int e)
{
	LNode * p; 
	p = L;
	int j = 0; //计数器
	while (p && (j < i - 1))
	{
		p = p->next;
		j++;
	}
	if (!p || (j > i - 1)) //i < 1 或者 i > n + 1  
	{
		return ERROR;
	}
	LNode *s = new LNode;
	s->data = e;
	s->next = p->next;
	p->next = s;
	return OK;
}

//单链表删除结点

/*
分析:
1,查找第i-1个系欸按,并让指针p指向该该节点
2,临时保存待删除结点的地址在q中,以备释放。
3,将结点*p的指针域指向第i个结点的直接后继结点
4,释放第i个结点的空间
*/

//删除单链表的第i个结点

bool ListDelete(Linklist &L, int i)
{
	LNode *p = L;
	int j = 0;
	while ((p->next) && (j < i - 1)) //查找第i-1个结点,p指向该结点
	{
		p = p->next;
		j++;
	}
	if ((p->next) || (j > i - 1)) //i<1 或者 i > n时,删除位置不合法
	{
		return ERROR;
	}
	Linklist q = p->next;
	p->next = p->next->next;
	delete q;
	return OK;
}

//前插法创建单链表
/*
分析:
1,创建一个只有头结点的空链表
2,根据待创建的链表包含的元素个数执行多次插入操作
(1),生成一个新节点
(2),输入元素值赋给新节点*p的数据域
(3)将新结点*p插入到头结点之后
*/

//逆次序输入n个元素的值,建立带有表头结点的单链表L
bool CreateList_H(Linklist &L, int n)
{
	L = new LNode;
	L->next = NULL;
	for (int i = 0; i < n; i++)
	{
		LNode *p = new LNode;
		cout << "please input an id :" << endl;
		cin >> p->data;
		p->next = L->next;
		L->next = p;
	}
	return OK;
}

//后插法创建单链表
/*
分析:
1,创建一个只有头结点的空链表
2,尾指针r初始化,指向头结点
3,根据创建链表包含的元素个数,循环n次操作:
(1)生成一个结点*p
(2)输入元素值,赋给新结点的数据域
(3)尾指针r指向新的尾结点*p
*/

//顺序输入n个元素的值
bool CreateList_R(Linklist &L, int n)
{
	L = new LNode;
	L->next = NULL;  //创建一个带表头的单链表
	LNode *r = L;
	for ( int i = 0; i < n ; i++)
	{
		LNode *p = new LNode; //生成新节点
		cout << "please input id " << endl;
		cin >> p->data;
		p->next = NULL;
		r->next = p;//将新结点*p插入到尾结点之后
		r = p; //将r指向新的尾节点
	}
	return OK;
}

//遍历单向链表

/*
1.获取链表的头结点并存储在指针*p中
2,循环操作 (循环结束条件p->next为空
(1)输出p->data数据域
(2)p指向下一个结点
*/

int  TraverseList(Linklist L)
{
	LNode * p = L->next; //指针指向头结点
	int j = 0;
	while (p) //下个结点不为空
	{
		j++;
		cout << "第 " << j << " 元素为:" << p->data << endl;
		p = p->next;
	} 
	return j;
}

//修改元素
/*
1,接收键盘输入的修改值
2,顺序遍历链表,找到该值,并进行修改(循环条件是p ->next !=NULL)
3,修改成功返回true,修改失败返回false
*/

bool ChangeElem(Linklist &L, int e)
{
	LNode * p = L->next;
	int j = 1;
	int value;
	while (p != NULL)
	{
		if (p->data == e)
		{
			cout << "你要修改的元素在第" << j << " 个位置," << "请输入修改后的值:";
			cin >> value;
			p->data = value;
			return  OK;
		}
		p = p->next;
		j++;
	}
	return false;
}







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

int main() {
	Linklist L;
	int flag3;
	cout << "输入1创建空链表,输入2,前插法创建链表,输入3,后插法创建链表 \n";
	cin >> flag3;
	switch (flag3)
	{
	case 1:
	{
		if (InitList(L))
		{
			cout << "创建成功。" << endl;
		}
		break;
	}
	case 2:
	{
		int n;
		cout << "请输入要输入的元素个数 :";
		cin >> n;
		if (CreateList_H(L, n))
		{
			cout << "创建成功。" << endl;
		}
		TraverseList(L);
		break;
	}
	case 3:
	{
		int n;
		cout << "请输入要输入的元素个数 :";
		cin >> n;
		if (CreateList_R(L, n))
		{
			cout << "创建成功。" << endl;
		}
		int total = TraverseList(L);
		cout << "链表总共有 " << total << " 个元素" << endl;
		break;
	}
	default:
	{
		cout << "你的输入有误,默认后插法创建链表\n";
		int n;
		cout << "请输入要输入的元素个数 :";
		cin >> n;
		if (CreateList_R(L, n))
		{
			cout << "创建成功。" << endl;
		}
		int total = TraverseList(L);
		cout << "链表总共有 " << total << " 个元素" << endl;
		break;
	}
	char flag = 'Y';
	int flag2;
	while (flag == 'y' || flag == 'Y')
	{
		cout << "输入4,插入元素,输入5,删除元素,输入6,查找元素,输入7,修改元素\n";
		cin >> flag2;
		switch (flag2)
		{

		case 4:
		{	cout << "当前链表的信息为:" << endl;
		int total = TraverseList(L);
		cout << "链表总共有 " << total << " 个元素" << endl;
		int e;
		cout << "请输入要插入的元素的值:\n";
		cin >> e;
		cout << "请输入要插入元素的位置 :\n";
		int index;
		cin >> index;
		if (ListInsert(L, index, e))
		{
			cout << "插入元素成功。" << endl;
		}
		else
		{
			cout << "插入元素失败。" << endl;
		}
		cout << "修改后链表的信息为:" << endl;
		total = TraverseList(L);
		cout << "链表总共有 " << total << " 个元素" << endl;
		break;
		}
		case 5:
		{
			cout << "当前链表的信息为:" << endl;
			int total = TraverseList(L);
			cout << "链表总共有 " << total << " 个元素" << endl;

			cout << "请输入要插入元素的位置 :\n";
			int index;
			cin >> index;
			if (ListDelete(L, index))
			{
				cout << "删除元素成功。" << endl;
			}
			else
			{
				cout << "删除元素失败。" << endl;
			}
			cout << "删除后链表的信息为:" << endl;
			total = TraverseList(L);
			cout << "链表总共有 " << total << " 个元素" << endl;
			break;
		}
		case 6:
		{
			int e;
			cout << "请输入要查找的元素的值:\n";
			cin >> e;
			LNode * address = LocateElem(L, e);
			if (address != NULL)
			{
				cout << "该元素存在,在内存中的地址为" << address << endl;
			}
			else
			{
				cout << "该元素不存在。";
			}
			break;
		}
		case 7:
		{
			int e;
			cout << "请输入你要进行修改的元素的值:";
			cin >> e;
			if (ChangeElem(L, e))
			{
				cout << "修改成功。" << endl << "修改后链表的值为" << endl;
				TraverseList(L);
			}
			break;
		}
		default:
			cout << "你的输入有误。" << endl;
			break;
		}

		cout << "继续其他操作请输入Y/y,退出请输入N/n" << endl;
		cin >> flag;
	}
	
	}
	system("pause");
}

静态链表(了解)

  • 用数组描述,游标实现法
  • 一个数据域,一个游标
  • 数组最后一个元素不存放数据,游标指向第一个有数据的元素(屁股指向头)
  • 数组第一个元素不存放数据,游标指向第一个没有数据的元素(头指向尾)

定义

在这里插入图片描述

初始化

在这里插入图片描述
在这里插入图片描述

插入

  • 根据游标指向下一个元素
    在这里插入图片描述
    在这里插入图片描述
  • 最后一个元素右边是0
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 有数据元素的最后一个是空的,指向备用元素的第一个

循环链表

循环链表的前插入法

#include <iostream>
using namespace std;
#define OK  true;
#define ERROR false;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {

   
    cout << "helloworld";
	return 0;
}
//循环链表定义 

typedef struct pNode{
	int data;
	struct pNode *next;
} pNode,* LinkList;
//初始化:前插入法 
 bool InitList(LinkList &L,int n)
{
	L = new pNode;
	L->next = NULL;
	pNode *p; 
	if(n != 0)
	{ 
     for(int i = 1;i <= n; i++ )
     {
        p = new pNode();
     	cin >> p->data;
     	p->next = L->next; //新的结点指向首元结点
		L->next = p;	//头结点指向新的新的结点,新结点成为首元结点
	 }
	 p -> next = L;  //将最后一个结点的指针域指向头结点 
	} 
	return OK; 
 } 
 
 bool InsertList(LinkList &L, int i, int e)
 {
 	pNode* p = L;
 	int j = 0;
 	while(p->next != L && j < i-1) //找到第i-1个结点 
	 {
	 	p = p -> next;
	 	j++;
	 }
	 if( p == L && j < i -1 ) 
	 {
	 	return ERROR ;	//指定位置 < 1 || i < n-1(超出了链表的范围) 
	  } 
 	
  } 
  /*
  >* 创建结点指针p,初始化为头指针
>* 遍历链表,指针p获取指定位置的前一个结点的指针,循环条件为(当前指针所指结点的指针域不为零 &&  当前位置小与指定位置的前一个结点)
>* 如果指定位置不合法则返回ERROR
>* 找到指定位置结点,保存该结点的指针,以备释放
>* 将指定位置前一个结点的指针域指向所找元素的下一个结点
>* 释放被删除的结点的资源

  */
  
bool DeleteList(LinkList &L,int i)
{
	int j = 0;
	pNode *p = L; 
	while(p->next !=L && (j < i-1) )
	{
		p = p ->next;
		j++;
	}
	if(p->next != L || j > i-1)  // i < 1 || i > n
		return ERROR;
	pNode * q = p->next;
	p->next = p->next->next;
	delete q;
	return OK;
	}

循环链表的后插入法以及链表的合并

void Connect_List(LinkList &A, LinkList &B)
{
pNode * p1 = A;
pNode * p2 = B;
while (p1->next != A)
{
p1 = p->next;
}
while (p2->next != B)
{
p2 = p2->next;
}
pNode * temp;

temp = B->next->next; //获取第二个链表的首元结点
B->next = A->next;
A->next = p;

}


    #include <iostream>
using namespace std;
#define OK  true;
#define ERROR false;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//循环链表定义 

typedef struct pNode {
	int data;
	struct pNode *next;
} pNode, *LinkList;

//初始化:尾插入法 

pNode * InitList( int n)
{
	pNode *head = new pNode();
	pNode *p = head;
	pNode * s = NULL;
	if (n != 0)
	{
		for (int i = 1; i <= n; i++)
		{
			s = new pNode();
			s->data = i;
			p->next = s; //把新结点的指针赋值给当前的结点的指针域
			p = s;	// 获取最后一个结点的地址
		}
		s->next = head->next;  //将最后一个结点的指针域指向头结点,形成一个环状 
	}
	delete head;
	return s->next; //返回首元结点的地址
}
int main(int argc, char** argv) {
	int n = 41;
	int m = 3;
	pNode * p = InitList( n);
	pNode * temp;
	while (p != p->next){
		for (int i = 1; i < m -1; i++) {
			p = p->next;
		}
		cout << p->next->data << "->";
		temp = p->next;
		p->next = temp->next;
		p = p->next;
	}
	cout << p->data;
	system("pause");
	return 0;
}

循环链表应用之魔术师发牌

// list_loop_connect.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

//循环链表定义 

#include "pch.h"
#include<iostream>
using namespace std;
const int cardnumber = 13;
typedef struct pNode
{
	int data;
	struct pNode * next;
}pNode,* LinkList ;

void CreateList(LinkList &L,int n)
{
	L = new pNode();
	L->next = NULL;
	pNode * r; //尾指针
	r = L; //指向当前指针
	for (int i = 1; i < cardnumber; i++)
	{
		pNode * p = new pNode();
		p->data = 0;
		p->next = NULL;
		r->next = p; //将p拼接到最后的位置
		r = p; //指针指向最后一个结点
	}
	r->next = L;
}
void InitList(LinkList &L)
{
	pNode * p;
	int j;
	int cn = 2;

	p = L; //指针指向首元结点
	p->data = 1;
	while (1)
	{
		for ( j = 0; j < cn; j++)
		{
			 p = p->next;
			if (p->data != 0)
			{
				//p = p->next;
				j--;
			}
		}

		if (p->data == 0)
		{
			p->data = cn;
			cn++;

			if (cn == 14)
			{
				break;
			}
		}
	}
}
int main()
{
	LinkList L;
	CreateList(L, cardnumber);
	InitList(L);
	pNode * p = L;
	while (p->next != L)
	{
		cout << p->data << "->";
		p = p->next;
	}
	cout << p->data;
	system("pause");
}

双链表

  • 结点具有两个指针域,一个指向前驱结点,一个指向后驱结点

定义

tepedef struct DuLNode{	
	Elemtype data;
	struct DuLNode * prior;
	struct DuLNode * next;
	} DuLNode ,*DuLinkList;

插入

bool ListInsert(DuLinkList &L, int i, Elemtype e)
{
	DuNode * p;
	if (! (p = GetElem(L, i)))
		return ERROR;
	DuNode *  s = new  DuNode;
	s->data = e;
	s->prior = p->prior;
	p->prior->next = s;
	s->next - p;
	p->prior = s;
	return  OK;
}

删除`

bool Delete(DuLinkList &L, int i, )
{
	DuNode * p;
	if (! (p = GetElem(L, i)))
		return ERROR;
	
	p->prior->next = p ->next;
	p->next->prior = p->prior;
	delete p;
	return  OK;
}

双向链表实现代码

// double_list.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

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

const bool ERROR = false;
const bool OK = true;

//双向链表结点1
typedef struct DuNode
{
	int data;
	struct DuNode * prior;
	struct DuNode * next;

}DuNode, * DuLinkList;

//在链表中特定的位置插入结点

DuLinkList GetElem(DuLinkList L, int i)
{
	
		DuNode * p = L->next;
		int j = 1;
		while (p && j < i)
		{
			
			p = p->next;
			j++;
		}
		if (!p || j > i)
			return ERROR;	
		return p;
}

bool TraverseList(DuLinkList L)
{
	if (L == NULL)
	{
		cout << "这是空链表。";
		return ERROR;
	}
	DuNode * p = L ->next ;
	int j = 0;
	while (p)
	{
		j++;
		cout << "第 " << j << " 个结点为 :" << p->data << endl;
		p = p->next;
	}
	return OK;

}

bool Create_head(DuLinkList &L, int n)
{
	L = new DuNode;
	L->next = NULL;
	L->prior = NULL;
	if (L == NULL)
	{
		cout << "创建失败";
		return ERROR;
	}
	DuNode * r = L; //尾指针

	for (int j = 1; j <= n; j++)
	{
		DuNode * p = new DuNode;
		if (p == NULL)
		{
			cout << "申请新结点失败。";
			return ERROR;
		}
		cout << "请输入第 " << j << " 个结点的数据(整数0 - 32767) :";
		cin >> p->data;
		p->next = NULL;
		p->prior = r;
		r->next = p;
		r = p;
	}
	cout << "创建成功" << endl;
	return OK;
}
bool InsertNode(DuLinkList &L, int i, int e)
{
	DuLinkList p;
	if (!(p = GetElem(L, i)))
		return  NULL;
	DuNode * s = new DuNode;
	s->data = e;
	s->next = p;
	s->prior = p->prior;
	p->prior->next = s;
	p->next->prior = s;
	cout << "插入成功,插入后的链表为:" << endl;
	TraverseList(L);
	return OK;
}
// 删除特定位置的结点
bool DeleteNode(DuLinkList &L, int i)
{
	DuNode * p;
	if (!(p = GetElem(L, i)))
		return  NULL;
	p->prior->next = p->next;
	p->next->prior = p->prior;
	delete p;
	cout << "删除成功,删除后的链表为:" << endl;
	TraverseList(L);
	return OK;
}

int main()
{
	DuLinkList L;
	Create_head(L, 10);
	int exits = 1;
	int flag = 3;
	int index_in;
	int index_out;
	TraverseList(L);
	while (flag != 0)
	{
		cout << "***********************************************************************************" << endl;
		cout << "请输入要进行的操作,插入数据输入 1 ,删除数据输入 2 ,遍历链表输入 3 ,退出输入 0  :" << endl;
		cout << "***********************************************************************************" << endl;
		cin >> flag;

		switch (flag)
		{
		case 2:
		{
			cout << "请输入要删除的结点的位置 :";
			cin >> index_out;
			DeleteNode(L, index_out);
			break;
		}
		case 1:
		{
			int e;
			cout << "请输入要添加的新节点的值 :";
			cin >> e;
			cout << endl;
			cout << "请输入要插入新结点的位置 :";
			cin >> index_in;
			cout << endl;
			InsertNode(L,index_in,e);
			break;
		}
		case 3:
		{
			cout << "当前的链表的内容为 :" << endl;
			TraverseList(L);
			break;
		}
		case 0: 
			exits = 0;
			break;
		default:
			cout << "你的输入有误。" << endl;
			break;
		}
	}
	return 0;
}

双向链表练习2


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

const int ERROR = 0;
const int OK = 1;

typedef char ElemType; //数据类型
typedef int Status;  //返回码

typedef struct DualNode
{
	ElemType data;
	struct DualNode	 *prior;
	struct DualNode *next;
}DualNode,* DuLinkList ;

Status InitList(DuLinkList &L) //尾插入法创建链表
{
	DualNode * p, *q;
	int i;
	L = new DualNode; //头结点
	if (L == NULL)
		return ERROR;
	L->next = NULL;
	L->prior = NULL;
	p = L; //尾指针
	for (int i = 0; i < 26; i++)
	{
		q = new DualNode;
		if (q == NULL)
		{
			cout << "申请新结点失败。";
			return ERROR;
		}

		q->data = 65 + i;
		q->prior = p;
		q->next = NULL;

		p->next = q;
		p = q;

	}
	cout << "原链表为:" << endl;
	DualNode * n= L->next;
	while (n)
	{

		cout << n->data << " ";
		n = n->next;
	}
	cout << endl;
	p->next = L->next;  //形成循环链表
	L->next->prior = p;
	return OK;
}

void Caesar(DuLinkList  &L, int i)
{
	
	if (i > 0)
	{
		do
		{
			 L= L->next;


		} while (--i);
	}
	if (i < 0)
	{
		do
		{
			L= L->next;

		} while (++i);
	}
}
int main()

{
	DuLinkList L;
	int n;
	InitList(L);
	cout << "请输入一个整数: ";
	cin >> n;
	cout << endl;
	Caesar(L, n);

	cout << "最终的链表:" << endl;
	DualNode * p = L->next;

	for (int i = 0; i < 26; i++)
	{
		cout << p->data << " ";
		p = p->next;
	}
	return OK;

}


运行结果
原链表为:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
请输入一个整数: 4
最终的链表:
E F G H I J K L M N O P Q R S T U V W X Y Z A B C D

原链表为:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
请输入一个整数: -2
最终的链表:
C D E F G H I J K L M N O P Q R S T U V W X Y Z A B

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值