数据结构--线性结构

目录

一、线性表的定义与实现

1.1线性表的定义

1.2线性表的顺序存储结构

1.2.1线性表的顺序存储结构的定义

1.2.2线性表的顺序存储结构的相关操作

1.3链式存储结构

1.3.1头结点与头指针的异同

1.4单链表结构与顺序存储结构的优缺点

二、广义表

三、栈

3.1栈的顺序存储

3.1.1定义

3.1.2.栈的操作

3.1.3两栈共享空间

3.3链式存储结构

四、队列

4.1队列的顺序存储

4.1.1队列的顺序存储结构定义及初始化

4.1.2队列的操作

4.2队列的链式存储

4.1.1队列的链式存储定义

4.2.2队列的链式存储的操作


一、线性表的定义与实现

1.1线性表的定义

线性表:零个或多个数据元素的有限序列。

“线性表”是由同一类型的数据结构构成的有序序列的线性结构。线性表中的元素的个数n称为线性表的长度;当一个线性表中没有元素(n=0)时,称为空表

表的起始位置称为表头,表的结束位置称为表尾。线性表中元素ai-1为ai的直接前驱,元素ai+1为ai的直接后继。在一个线性表中,ai有且仅有一个直接前驱,有且仅有一个直接后继。第一个元素无前驱,最后一个元素无后继。

 1.线性表强调是有限的

2.线性表为一个序列,即元素之间是有顺序的。

1.2线性表的顺序存储结构

1.2.1线性表的顺序存储结构的定义

线性表的顺序存储,是在内存中用地址连续的一块存储空间顺序存放线性表的各元素。

在程序设计语言中,一维数组在内存中占用的存储空间就是一组连续的存储空间,因此,用一维数组来表示顺序存储的数据区域。以Data[MAXSIZE]为例:

顺序存储结构:

#define MAXSIZE 20//存储空间初始分配量
typedef int ElementType;//ElementType类型根据实际情况而定
typedef struct
{
	ElementType Data[MAXSIZE];//数组存储数据元素
	int length;//线性表当前长度
}SqList;

 或

#define MAXSIZE 20//存储空间初始分配量
typedef int ElementType;//ElementType类型根据实际情况而定
typedef struct
{
	ElementType *elem;//存储空间的基地址-即首元素地址
	int length;//线性表当前长度
}SqList;

描述线性表的顺序存储结构需要三个属性:

1.存储空间的起始位置:数组Data的首元素地址。

2.线性表的最大存储容量:数组最大长度MAXSIZE。

3.线性表的当前长度:length。

可以利用SqList定义线性表L或者线性表的指针p:

SqList L,*p;

通过L或p可以访问相应线性表的内容。

1.2.2线性表的顺序存储结构的相关操作

1.初始化

顺序表的初始化即构造一个空表。首先动态分配表解构所需要的存储空间,将表长置0;

typedef struct
{
	ElementType Data[MAXSIZE];//数组存储数据元素
	int length;//线性表当前长度
}SqList;

SqList* Inite()
{
	SqList* p;
	p = new SqList;
	p->length = 0;
	return p;
}


int main()
{
	SqList * L1 = Inite();
	
}

 或


typedef struct
{
	ElementType* elem;//存储空间的基地址-即首元素地址
	int length;//线性表当前长度
}SqList;

int Inite(SqList & L)
{//申请分配空间
	//L.elem = (ElementType*)malloc(MAXSIZE * (sizeof(ElementType)));
	L.elem = new ElementType[MAXSIZE];
	if (!L.elem)//空间分配失败返回NULL
	{
		exit(ERROR);
	}
	L.length = 0;
	return OK;
}
int main()
{
	SqList L;
	Inite(L);
	
}

2.赋值

int Value(SqList* L)
{
	int num = 0,i=0;
	cin >> num;//输入元素个数
	if (L->length == MAXSIZE||num>MAXSIZE)//线性表已满或者元素个数多
		return ERROR;
	while (num--)
	{
		cin >> L->Data[i];
		i++;
		L->length++;
	}
	return OK;
}

3.查找

在线性表中找与给定值x相同的数据元素。找到返回其下标,未找到返回-1。

int Find(ElementType X, SqList* L)//使用指针传输效率高
{
	int i = 0;
	while (i < L->length)
	{
		if (L->Data[i] == X)
			return i;
		else
			i++;
	}
	return -1;
}

4.插入

int Insert(int i, ElementType e, SqList* L)
{
	if (L->length == MAXSIZE)//表满,不能插入
		return -1;
	if (i<1 || i>L->length)//插入位置不合法
		return -1;
	if (i <= L->length)//插入位置不在表尾
	{
		for (int k = L->length - 1; k >= i - 1; k--)
			L->Data[k + 1] = L->Data[k];//将要插入位置后的数据元素向后移动
	}
	L->Data[i - 1] = e;
	L->length++;
	return OK;

}

5.删除

将第i个元素从表中去掉

int Delete(int i , SqList* L)
{
	if (i<1 || i>L->length)//删除位置不合理
		return ERROR;
	for (int j = i; j < L->length; j++)//将后边元素向前移
		L->Data[j - 1] = L->Data[j];
	L->length--;
	return OK;
}

综合代码:

#include <iostream>
using namespace std;
#define MAXSIZE 20//存储空间初始分配量
#define OK 1
#define ERROR 0
typedef int ElementType;//ElementType类型根据实际情况而定
typedef struct
{
	ElementType Data[MAXSIZE];//数组存储数据元素
	int length;//线性表当前长度
}SqList;
SqList* Inite()
{
	SqList* p;
	p = new SqList;
	p->length = 0;
	return p;
}
int Value(SqList* L)
{
	int num = 0,i=0;
	cin >> num;//输入元素个数
	if (L->length == MAXSIZE||num>MAXSIZE)//线性表已满或者元素个数多
		return ERROR;
	while (num--)
	{
		cin >> L->Data[i];
		i++;
		L->length++;
	}
	return OK;
}
int Find(ElementType X, SqList L)//相当于原L的复制品
{
	int i = 0;
	while (i < L.length)
	{
		if (L.Data[i] == X)
			return i;
		else
			i++;
	}
	return -1;
}
int Insert(int i, ElementType e, SqList* L)
{
	if (L->length == MAXSIZE)//表满,不能插入
		return -1;
	if (i<1 || i>L->length)//插入位置不合理
		return -1;
	if (i <= L->length)//插入位置不在表尾
	{
		for (int k = L->length - 1; k >= i - 1; k--)
			L->Data[k + 1] = L->Data[k];//将要插入位置后的数据元素向后移动
	}
	L->Data[i - 1] = e;
	L->length++;
	return OK;

}
int Delete(int i , SqList* L)
{
	if (i<1 || i>L->length)//删除位置不合理
		return ERROR;
	for (int j = i; j < L->length; j++)//将后边元素向前移
		L->Data[j - 1] = L->Data[j];
	L->length--;
	return OK;
}
void Print(SqList L)
{
	for (int i = 0; i < L.length; i++)
	{
		cout << L.Data[i]<<" ";
	}
	printf("\n");
}
int main()
{
	SqList * L = Inite();
	Value(L);
	
	int i = 0,k=0;
	ElementType e;
	cin >> i >> e;
	Insert(i,e,L);
	cin >> k;
	Delete(k, L);
	Print(*L);
	return 0;
}

顺序存储的缺点:插入删除时需要大量移动元素,故引入链式存储结构

1.3链式存储结构

见博客:http://t.csdn.cn/yh4mT

补充:

1.3.1头结点与头指针的异同

头指针:

1.头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。

2.头指针具有标识作用,所以常以头指针冠以链表的名字。

3.无论链表是否为空,头指针均不为空。头指针是链表的必要元素。

头结点:

1.头结点是为了操作的统一和方便而设立的,放在第一个元素之前,其数据域一般无意义。

2.有了头结点,对在第一元素节点前插入结点和删除第一节点,其操作就统一了。

3.头结点不是链表的必要元素。

1.4单链表结构与顺序存储结构的优缺点

1.若线性表需要频繁查找,很少进行插入删除操作,宜采用顺序存储结构

2.若需要频繁进行插入,删除操作,宜采用单链表结构。

3.线性表元素确定时,宜采用顺序存储结构;线性表中元素个数变化较大或不知道元素个数时,最好采用单链表结构。

二、广义表

广义表是线性表的推广,也称为列表,与线性表一样,也是由n个元素组成的有序序列。

一般形式:

LS=(a1,a2,...,ai...,an);

在广义表的定义中,ai可为单个元素,也可以是广义表,分别称为广义表LS的原子和子表。习惯上,用大写字母表示广义表的名称,用小写字母表示原子。

 由此,广义表的定义是一个递归的定义,例子:

  • A = ():A 表示空表,其长度为0。
  • B = (e)--B 长度为1,,只有一个原子 e。
  • C = (a,(b,c,d)) --C 的长度为2,两个元素分别是原子 a 和子表 (b,c,d)。
  • D = (A,B,C)--D的长度为3,3个元素均是广义表。 D = ((),(e),(b,c,d)) 。
  • E = (a,E)--这是一个递归表,其长度为2。E相当于一个无限的广义表E = (a,(a,(a,…)))。

由于广义表中的元素可以具有不同的结构(单元素或者广义表),因此不适合采用顺序存储方式表示,通常采用链式存储表示。

分析知,广义表的结点有两种情况:

1.单元素,需要有一个域来存储该单元素的值。

2.广义表,需要有一个域来指向另一个链表。

上述两个域可能只需要其中一种,所以,可以利用共用体来实现这两个域的复用。

typedef struct LGNode
{
	int Tag;//标志域:0表示该节点是单元素,1表示该结点是广义表
	union
	{
		ElementType atom;//原子结点的值域
		struct
		{
			struct GLNode* hp;
		}ptr;//ptr是表节点的指针域,ptr.hp分别指向表头和表尾
	};
	struct GLNode* tp;//tp指向后继结点
}GLNode,*GList;

 

 两个最重要的运算

1.取表头GetHead(LS):取出的表头为非空广义表的第一个元素,可以是一个单原子也可以是一个子广义表。

2.取表尾GetTail(LS):取出的表尾为除去表头后其余元素构成的表,即表尾一定是一个广义表。

例如:

B = (e),D=(A,B,C)

GetHead(B)=e,GetHead(D)=A

GetTail(B)=(),GetTail(D)=(B,C) 继续分解:GetHead(B,C)=B,GetTail(B,C)=(C)。

注:对广义表()和(())不同,前者为空表,长度为0;后者不为空表长度为1,可分解得到表头和表尾均为空表

广义表的长度和深度

广义表的长度,指的是广义表中所包含的数据元素的个数

计算元素个数时,广义表中存储的每个原子算作一个数据,同样每个子表也只算作是一个数据

广义表的深度,可以通过观察该表中所包含括号的层数间接得到。

eg:A=(a,b,c,(d,(e,f))->长度为4,深度为3

三、栈

栈和队列也是线性表,它们是操作受限的线性表。

栈是限定仅在表尾进行插入和删除操作的线性表。

允许插入和删除的一段称为栈顶(top),另一端称为栈底(bottom),不含元素的栈称为空栈。栈又称为后进先出(Last In First Out,简称LIFO线性表)的线性表。

3.1栈的顺序存储

3.1.1.定义:

#define MAXSIZE 100//存储数据元素的最大数量
typedef struct
{
	ElementType data[MAXSIZE];
	int top;//栈顶指针
}SqStack;

3.1.2.栈的操作

1.入栈操作Push

首先判断栈是否已满,若不满,栈顶指针+1,新元素e入栈

int Push(SqStack* s, ElementType e)
{
	if (s->top == MAXSIZE - 1)//栈已满
		return ERROR;
	s->top++;
	s->data[s->top] = e;
	return OK;
}

2.出栈操作Pop

首先判别栈是否空,若不空,返回栈顶元素,栈顶指针-1

int Pop(SqStack* s)
{
	if (s->top == 0)//栈空
		return ERROR;
	ElementType e;
	e = s->data[s->top];
	s->top--;
	return e;
}

综合:


#include <iostream>
using namespace std;
#define OK 1
#define ERROR -1
#define MAXSIZE 100//存储数据元素的最大数量
typedef  int ElementType;
typedef struct
{
	ElementType data[MAXSIZE];
	int top;//栈顶指针
}SqStack;
SqStack* Inite()
{
	SqStack* s;
	s = new SqStack;
    if (!s)//分配空间失败
		return ERROR;
	s->top = 0;
	return s;
}
int Push(SqStack* s, ElementType e)
{
	if (s->top == MAXSIZE - 1)//栈已满
		return ERROR;
	s->top++;
	s->data[s->top] = e;
	return OK;
}
int Pop(SqStack* s)
{
	if (s->top == 0)//栈空
		return ERROR;
	ElementType e;
	e = s->data[s->top];
	s->top--;
	return e;
}
void Print(SqStack s)
{
	int num = s.top;
	while (num!=0)
	{
		cout << s.data[num] << " ";
		num--;
	}
	cout << endl;
	return;
}
int main()
{
	SqStack *s=Inite();
	ElementType e;
	int num = 0;
	cin >> num;//输入元素个数
	while (num--)
	{
		cin >> e;
		Push(s, e);
	}
	Print(*s);
	cout<<Pop(s)<<endl;
	Print(*s);
	return 0;
}
输入:
5
1 2 3 4 5
输出:
5 4 3 2 1
5
4 3 2 1


3.1.3两栈共享空间

数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的起始端,即下标为0处,另一个栈为数组的末端,即下标为MAXSIZE-1处。两个栈如果增加元素,就是两端向中间延伸;当两个栈的栈顶指针相遇,表示两个栈都满了

1.定义: 

typedef struct
{
	ElementType data[MAXSIZE];
	int top1;//栈顶指针
	int top2;
}SqDStack;

 对两个栈的初始化方法:top1=-1;top=MAXSIZE;

2. 入栈

int Push(SqDStack* s, ElementType e,int stacknum)
{
	if (s->top1+1==s->top2)//栈已满
		return ERROR;
	if (stacknum == 1)
	{
		s->top1++;
		s->data[s->top1] = e;
	}
	else if (stacknum == 2)
	{
		s->top2--;
		s->data[s->top2] = e;
	}
	else
		cout << "栈号输入错误" << endl;
	return OK;
}

3.出栈

int Pop(SqDStack* s,int stacknum)
{
	ElementType e=0;
	if (stacknum == 1)
	{
		if (s->top1 == -1)//栈1空
			return ERROR;
		e = s->data[s->top1];
		s->top1--;
	}
	else if (stacknum == 2)
	{
		if (s->top2 == MAXSIZE)
			return ERROR;
		e = s->data[s->top2];
		s->top2++;
	}
	else
		cout << "栈号输入错误" << endl;
	return e;
}

综合:


#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define MAXSIZE 100//存储数据元素的最大数量
typedef  int ElementType;
typedef struct
{
	ElementType data[MAXSIZE];
	int top1;//栈顶指针
	int top2;
}SqDStack;


SqDStack* Inite()
{
	SqDStack* s;
	s = new SqDStack;
	if (!s)//分配空间失败
		return ERROR;
	s->top1 = -1;
	s->top2 = MAXSIZE;
	return s;
}
int Push(SqDStack* s, ElementType e,int stacknum)
{
	if (s->top1+1==s->top2)//栈已满
		return ERROR;
	if (stacknum == 1)
	{
		s->top1++;
		s->data[s->top1] = e;
	}
	else if (stacknum == 2)
	{
		s->top2--;
		s->data[s->top2] = e;
	}
	else
		cout << "栈号输入错误" << endl;
	return OK;
}
int Pop(SqDStack* s,int stacknum)
{
	ElementType e=0;
	if (stacknum == 1)
	{
		if (s->top1 == -1)//栈1空
			return ERROR;
		e = s->data[s->top1];
		s->top1--;
	}
	else if (stacknum == 2)
	{
		if (s->top2 == MAXSIZE)
			return ERROR;
		e = s->data[s->top2];
		s->top2++;
	}
	else
		cout << "栈号输入错误" << endl;
	return e;
}
void Print(SqDStack s,int stacknum)
{
	int num;
	if (stacknum == 1)
	{
		num = s.top1;
		while (num != -1)
		{
			cout << s.data[num] << " ";
			num--;
		}
	}
	else if (stacknum == 2)
	{
		num = s.top2;
		while (num != MAXSIZE)
		{
			cout << s.data[num] << " ";
			num++;
		}
	}
	else
		cout << "栈号输入错误" << endl;
	cout << endl;
	return;
}
int main()
{
	SqDStack *s=Inite();
	ElementType e;
	for(int i=0;i<3;i++)
	{
		cin >> e;
		Push(s,e,1);
	}
	for (int i = 0; i < 3; i++)
	{
		cin >> e;
		Push(s, e, 2);
	}
	Print(*s,1);
	Print(*s,2);
	cout<<Pop(s,1)<<"\n"<<Pop(s,2) << endl;
	Print(*s,1);
	Print(*s,2);
	return 0;
}
输入:
1 2 3 4 5 6
输出:
3 2 1
6 5 4
3
6
2 1
5 4

3.3链式存储结构

栈的链式存储结构与单链表的类似,但其操作受限。

综合代码:


#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
typedef  int ElementType;
typedef struct StackNode
{
	ElementType data;
	struct StackNode* next;
}StackNode,*LinkStack;

int Inite(LinkStack &s)
{
	s= NULL;//构造一个空栈,栈顶指针置空
	return OK;
}
int Push(LinkStack& s, ElementType e)
{
	StackNode *p = new StackNode;//生成新节点
	p->data = e;
	p->next = s;
	s = p;
	return OK;
}
int Pop(LinkStack& s)
{
	if (s == NULL)//空栈
		return ERROR;
	ElementType  e;
	StackNode* p = new StackNode;
	e = s->data;
	p = s;//p临时保留栈顶元素,以备释放
	s = s->next;
	delete p;
	return OK;
	
}
void Print(LinkStack s)
{
	StackNode* p = new StackNode;
	p = s;
	while (p != NULL)
	{
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
	return;
}
int main()
{
	LinkStack s;
	Inite(s);
	ElementType e;
	for (int i = 0; i < 3; i++)
	{
		cin >> e;
		Push(s, e);
	}
	Print(s);
	cout<<Pop(s);
	Print(s);
	return 0;
}



补充:栈的一种类型题:判断哪种入栈出栈序列不符合

eg: 将ABCD这4个字符按顺序压入堆栈,可以产生CBAD、ADBC序列吗?

对序列判断,如果最前面出栈的元素是后面压入的,那么提前压入的元素出栈的顺序就一定只能是压入元素顺序的逆序。

上面那句话不太好理解,有一个小技巧,将字符按输入顺序竖着排列,从序列开始划线,可以往上隔着字母划线,不能向下隔字母划线,线一旦中断,就说明这个序列不可能出现。举个例子:CBAD

序列ADBC:D-B段隔着C不能划线,线中断,故该序列不能实现 

 

四、队列

队列是只允许在一端进行插入操作、而在另一端进行删除操作的线性表。

队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头

4.1队列的顺序存储

随着入队、出队操作的进行,会出现“假溢出”的现象。

 为解决队尾假溢出现象,一般在队列的顺序存储结构中采用循环队列的方式:

队列的头尾相接的顺序存储结构称为循环队列。

 又出现一个问题,当front和rear值相等时,队列可能为空或者为满,无法判别。

有两个办法:

一、设置一个标志变量flag,当front=rear,且flag=0时队列为空,当front=rear,且flag=1时为队列满。

二、当队列为空时,front=rear;当队列为满时,条件修改为(rear+1)%数组长度=front。

一般选用方法2。

4.1.1队列的顺序存储结构定义及初始化:

typedef struct
{
	ElementType* base;//存储空间基地址
	int front;//队头指针
	int rear;//尾指针
}SqQueue;
int Inite(SqQueue & Q)
{
	Q.base = new ElementType[MAXSIZE];//为队列分配数组空间
	if (!Q.base) exit(ERROR);
	Q.front = Q.rear = 0;
	return OK;
}

或:

typedef struct
{
	ElementType data[MAXSIZE];
	int front;//队头指针
	int rear;//尾指针
}SqQueue;

int Inite(SqQueue* Q)
{
	Q->front = 0;
	Q->rear = 0;
	return OK;
}

4.1.2队列的操作

1.循环队列的插入--入队

int EnQueue(SqQueue* Q, ElementType e)
{
	//判断队是否满
	if ((Q->rear + 1) % MAXSIZE == Q->front)
		return ERROR;
	Q->data[Q->rear] = e;
	Q->rear = (Q->rear + 1) % MAXSIZE;//rear后移一位
	return OK;
}

2.循环队列的删除--出队

ElementType DeQueue(SqQueue* Q)
{
	//判断队是否为空
	if (Q->front == Q->rear)
		return ERROR;
	ElementType e;
	e = Q->data[Q->front];
	Q->front = (Q->front + 1) % MAXSIZE;//front后移一位
	return e;
}

3.求循环队列的长度

int QueueLength(SqQueue Q)
{
	return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}

综合:


#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define MAXSIZE 100
typedef  int ElementType;
typedef struct
{
	ElementType data[MAXSIZE];
	int front;//队头指针
	int rear;//尾指针
}SqQueue;

int Inite(SqQueue* Q)
{
	Q->front = 0;
	Q->rear = 0;
	return OK;
}

int EnQueue(SqQueue* Q, ElementType e)
{
	//判断队是否满
	if ((Q->rear + 1) % MAXSIZE == Q->front)
		return ERROR;
	Q->data[Q->rear] = e;
	Q->rear = (Q->rear + 1) % MAXSIZE;//rear后移一位
	return OK;
}

ElementType DeQueue(SqQueue* Q)
{
	//判断队是否为空
	if (Q->front == Q->rear)
		return ERROR;
	ElementType e;
	e = Q->data[Q->front];
	Q->front = (Q->front + 1) % MAXSIZE;//front后移一位
	return e;
}

int QueueLength(SqQueue Q)
{
	return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}

void Print(SqQueue Q)
{
	while (Q.front != Q.rear)
	{
		cout << Q.data[Q.front] << " ";
		Q.front = (Q.front + 1) % MAXSIZE;
	}
	cout << endl;
	return;
}

int main()
{
	SqQueue Q;
	Inite(&Q);
	ElementType e;
	for (int i = 0; i < 5; i++)
	{
		
		cin >> e;
		EnQueue(&Q, e);
	}
	Print(Q);
	cout <<"长度1:"<< QueueLength(Q) << endl;
	cout<<DeQueue(&Q)<<endl;
	cout << "长度2:" << QueueLength(Q) << endl;
	Print(Q);
	return 0;
}



4.2队列的链式存储

为了操作的方便,我们将队头指针指向链队列的头结点,而队尾指针指向终端结点。

4.1.1队列的链式存储定义:

typedef struct QNode//结点结构
{
	ElementType data;
	struct QNode* next;
}QNode,*QueuePtr;
typedef struct//队列的链表结构
{
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

4.2.2队列的链式存储的操作

1.初始化

int Inite(LinkQueue* Q)
{
	Q->front = Q->rear = new QNode;//生成新节点作为头结点,队头和队尾都指向此节点
	Q->front->next = NULL;//头结点的指针域值空
	return OK;
}

2.入队 

int EnQueue(LinkQueue* Q, ElementType e)
{
	QueuePtr p = new QNode;//为元素申请新节点
	p->data = e;
	p->next = NULL;
	Q->rear->next = p;//将新节点插入队尾
	Q->rear = p;//修改队尾指针
	return OK;
}

3.出队

ElementType DeQueue(LinkQueue* Q)
{
	if (Q->front == Q->rear)//队列为空
		return ERROR;
	ElementType e;
	QueuePtr p = new QNode;
	p = Q->front->next;//p指向将要删除的队头元素
	e = p->data;
	Q->front->next = p->next;//修改头结点的指针域
	if (Q->rear == p)//最后一个元素被删,队尾指针指向头结点
		Q->rear = Q->front;
	delete p;//释放原头结点元素的空间
	return e;
}

综合:


#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define MAXSIZE 100
typedef  int ElementType;
typedef struct QNode//结点结构
{
	ElementType data;
	struct QNode* next;
}QNode, * QueuePtr;
typedef struct//队列的链表结构
{
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

int Inite(LinkQueue* Q)
{
	Q->front = Q->rear = new QNode;//生成新节点作为头结点,队头和队尾都指向此节点
	Q->front->next = NULL;//头结点的指针域值空
	return OK;
}

int EnQueue(LinkQueue* Q, ElementType e)
{
	QueuePtr p = new QNode;//为元素申请新节点
	p->data = e;
	p->next = NULL;
	Q->rear->next = p;//将新节点插入队尾
	Q->rear = p;//修改队尾指针
	return OK;
}

ElementType DeQueue(LinkQueue* Q)
{
	if (Q->front == Q->rear)//队列为空
		return ERROR;
	ElementType e;
	QueuePtr p = new QNode;
	p = Q->front->next;//p指向将要删除的队头元素
	e = p->data;
	Q->front->next = p->next;//修改头结点的指针域
	if (Q->rear == p)//最后一个元素被删,队尾指针指向头结点
		Q->rear = Q->front;
	delete p;//释放原头结点元素的空间
	return e;
}

void Print(LinkQueue Q)
{
	ElementType e;
	QueuePtr p = new QNode;
	p = Q.front;
	do
	{
		p=p->next;
		cout <<p->data<< " ";
		
	}while (p != Q.rear);
	cout << endl;
	return;
}

int main()
{
	LinkQueue Q;
	Inite(&Q);
	ElementType e;
	for (int i = 0; i < 5; i++)
	{
		cin >> e;
		EnQueue(&Q, e);
	}
	Print(Q);
	cout<<DeQueue(&Q)<<endl;
	Print(Q);
	return 0;
}
输入:
1 2 3 4 5
输出:
1 2 3 4 5
1
2 3 4 5

 参考书籍:严蔚敏、李冬梅、吴伟民老师的《数据结构》、程杰老师的《大话数据结构》、陈越老师的《数据结构》。有问题欢迎指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值