数据结构

顺序表的操作(C++实现)

顺序表的基本操作

设计思想:

  • 线性表结构体定义:线性表长度,存储空间的基址是一个定义元素类型的指针型变量
  • 线性表初始化:给L的存储基址分配空间(用定义元素类型的数组),判断基址是否为空来确定是否分配存储空间成功
  • 清空线性表:将线性表的长度置0
  • 检查线性表是否为空:看线性表的长度是否为空
  • 获取特定位置的元素:先判断输入位置是否合法,通过L的基地址(数组)调用
  • 查找元素的前驱和后继:先判断输入位置是否合法,判断该位置的元素是否有前驱或后继,通过L的基地址(数组)调用
  • 插入元素:先判断输入位置是否合法,再判断存储空间是否存满,倒序将元素往后赋值,最后线性表长度加一
  • 删除元素:先判断输入位置是否合法,顺序从输入位置的下一个元素开始向前赋值
  • 销毁线性表:用delete释放elem数组的内存,把线性表的长度置为0,L的基址置为null
#include<iostream>
#include<algorithm>
using namespace std;
//预定义常量和类型
  //常量
#define MAXSIZE 1000 
  //函数结果状态码
#define OK 1
#define ERROR 0
#define SqList_overflow -2
  // Status 是函数返回值类型,其值是函数结果状态码
typedef int Status;
//数据元素类型约定为ElemType
typedef int ElemType;

//顺序表的建立,定义了一个名为SqList的结构体
struct SqList {
	//当前长度
	int length;
	//存储空间的基地址
	ElemType* elem;
};

//初始化顺序表
Status SqList_Init(SqList&);
//顺序表读入值
void SqList_read(int, SqList&);
//清空线性表
Status SqList_clear(SqList&);
//判断线性表是否为空
Status SqList_check_null(SqList&);
//求线性表长度
Status SqList_getLength(SqList&);
//获取线性表指定位置元素
Status SqList_getElem(SqList&);
//求前驱
Status SqList_elemPrecursor(SqList&);
//求后继
Status SqList_elemNext(SqList&);
//在线性表指定位置插入元素
Status SqList_elemInsert(SqList&);
//删除线性表指定位置元素
Status SqList_elemDelete(SqList&);
//显示线性表
Status SqList_display(SqList&);
//销毁线性表
Status SqList_Destory(SqList&);
//检索值为e的元素
Status SqList_elemIse(SqList&);

//判断操作代码
void check_n(int, SqList& L);
//显示菜单
void Menu();
//检查各个操作返回的状态值
void Status_check(int);
//测试过程
void Test();

int main() {
	Test();
}

void Test() {
	int n;
	//初始化一个顺序表
	SqList L;
	if (SqList_Init(L) == -2) {
		return;//void 函数结束程序。。。
	}
	//给顺序表赋值
	int m;//把m个元素放入顺序表
	for (;;) {
		cout << "请输入顺序表的元素个数m:" << endl;
		cin >> m;
		if (m < 0) {
			cout << "请输入合法的顺序表的元素个数m:" << endl;
		}
		else break;
	}
	SqList_read(m, L);
	for (;;) {
		//显示菜单
		Menu();
		//输入操作码
		for (;;) {
			cout << "请输入操作代码" << endl;
			cout << "        输入负数退出" << endl;
			cin >> n;
			if (n >= 1 && n <= 11) {
				//根据操作码选择操作
				check_n(n, L);				
			}
			else if (n < 0) {
				return;
			}
			else {
				cout << "请输入正确操作码" << endl;
			}
		}
	}
}
void Menu() {
	cout << endl;
	cout << "1812030065  李诗雨" << endl;
	cout << "1-------清空线性表" << endl;
	cout << "2-------判断线性表是否为空" << endl;
	cout << "3-------求线性表长度" << endl;
	cout << "4-------获取线性表指定位置元素" << endl;
	cout << "5-------求前驱" << endl;
	cout << "6-------求后继" << endl;
	cout << "7-------在线性表指定位置插入元素" << endl;
	cout << "8-------删除线性表指定位置元素" << endl;
	cout << "9-------显示线性表" << endl;
	cout << "10-------销毁线性表" << endl;
	cout << "11-------检索值为e的元素" << endl;

}
void Status_check(int n) {
	if (n == 0) return ;
	if (n == -2) return;
}
void check_n(int n, SqList& L) {
	


	//不要忘了每个case里都要break
	switch (n)
	{
	case 1:		
		Status_check(SqList_clear(L));
		break;
	case 2:
		Status_check(SqList_check_null(L));
		break;
	case 3:
		Status_check(SqList_getLength(L));
		break;
	case 4:
		Status_check(SqList_getElem(L));
		break;
	case 5:
		Status_check(SqList_elemPrecursor(L));
		break;
	case 6:
		Status_check(SqList_elemNext(L));
		break;
	case 7:
		Status_check(SqList_elemInsert(L));
		break;
	case 8:
		Status_check(SqList_elemDelete(L));
		break;
	case 9:
		Status_check(SqList_display(L));
		break;
	case 10:
		Status_check(SqList_Destory(L));
		break;
	case 11:
		Status_check(SqList_elemIse(L));
		break;
	default:
		break;
	}

}
Status SqList_Init(SqList& L) {
	//构造一个新的顺序表L 并为之分配大小为MAXSIZE的空间
	L.elem = new ElemType[MAXSIZE];//关于elemtype...

	if (L.elem == NULL) {
		cout << "存储空间分配失败!" << endl;
		return SqList_overflow;
	}
	L.length = 0;
	cout << "顺序表初始化成功" << endl;
	return OK;
}
void SqList_read(int m, SqList& L) {
	for (int i = 0; i < m; i++) {
		ElemType e;
		cin >> e;
		L.elem[i] = e;
		L.length++;
	}
}
Status SqList_clear(SqList& L)
{
	L.length = 0;
	Status_check(SqList_display(L));
	return OK;
}
Status SqList_check_null(SqList& L)
{
	if (L.length == 0) {
		cout << "null" << endl;
	}
	else {
		cout << "not null" << endl;
	}
	return OK;
}
Status SqList_getLength(SqList& L) {
	cout << "顺序表的长度为:" << L.length << endl;
	return OK;
}
Status SqList_getElem(SqList& L) {
	int p;
	//判断输入位置是否合法
	for (;;) {
		cout << "请输入要查找元素的位置" << endl;
		cin >> p;
		if (p < 0 || p >= L.length) {
			cout << "输入位置不合法" << endl;
		}
		else break;
	}
	cout << p << "位置上的元素是:" << L.elem[p] << endl;
	Status_check(SqList_display(L));
	return OK;
}
Status SqList_elemPrecursor(SqList& L) {
	int p;
	//判断输入位置是否合法
	for (;;) {
		cout << "请输入要查找元素前驱的位置" << endl;
		cin >> p;
		if (p < 1 || p >= L.length) {
			cout << "输入位置不合法" << endl;
		}
		else break;
	}
	cout << p << "位置的前驱元素是: " << L.elem[p - 1] << endl;
	Status_check(SqList_display(L));
	return OK;
}
Status SqList_elemNext(SqList& L) {
	int p;
	//判断输入位置是否合法
	for (;;) {
		cout << "请输入要查找元素后继的位置" << endl;
		cin >> p;
		if (p < 0 || p >= L.length-1) {
			cout << "输入位置不合法" << endl;
		}
		else break;
	}
	cout << p << "位置的后继元素是: " << L.elem[p + 1] << endl;
	Status_check(SqList_display(L));
	return OK;
}
Status SqList_elemInsert(SqList& L) {
	int p;
	//判断输入位置是否合法
	for (;;) {
		cout << "请输入要插入的位置" << endl;
		cin >> p;
		if (p < 0 || p >= L.length+1) {
			cout << "输入位置不合法" << endl;
		}
		else break;
	}
	//查看存储空间是否已满
	if (L.length == MAXSIZE)
	{
		cout << "存储空间已满" << endl;
		return ERROR;
	}

	cout << "请输入要插入的元素" << endl;
	ElemType e;
	cin >> e;
	for (int i = L.length; i > p; i--) {
		L.elem[i] = L.elem[i - 1];
	}
	L.elem[p] = e;
	L.length++;
	Status_check(SqList_display(L));
	return OK;
}
Status SqList_elemDelete(SqList& L) {
	int p;
	//判断删除的位置是否合法
	for (;;) {
		cout << "请输入要删除的元素的位置" << endl;
		cin >> p;
		if (p < 0 || p >= L.length) {
			cout << "输入位置不合法" << endl;
		}
		else break;
	}
	for (int i = p; i < L.length - 1; i++) {
		L.elem[i] = L.elem[i + 1];
	}
	L.length--;
	Status_check(SqList_display(L));
	return OK;
}
Status SqList_display(SqList& L) {
	cout << "更新后的L:" << endl;
	if (L.length == 0) {
		cout << "该顺序表为空" << endl;
	}
	else {
		for (int i = 0; i < L.length; i++) {
			cout << L.elem[i] << ",";
		}
		cout << endl;
	}
	return OK;
}
Status SqList_Destory(SqList& L) {
	if (L.elem)
		delete[] L.elem;    //释放存储空间
	L.length = 0;
	L.elem = NULL;
	cout << "该线性表已销毁" << endl;
	return OK;
}
Status SqList_elemIse(SqList& L) {
	ElemType e;
	cout << "请输入要查找的元素" << endl;
	cin >> e;
	for (int i = 0; i < L.length; i++) {
		if (L.elem[i] == e) {
			cout << i << "位置" << endl;
		}
	}
	return OK;
}

结果:
顺序表的基本操作1
顺序表的基本操作2
顺序表的基本操作3

两个集合的运算:交集/并集/差集。

遇到的问题与解决

  • 实现并集的方法
      本来最先想到的是AB的交集+A-B+B-A,但是这样做还要把这三个结果合并成一个表,尝试实现了,有点点麻烦。而且发现了下一个问题。
    解决:
      建立C表,遍历A,如果没有在B出现过,就加在B表里面
  • 结构体的深拷贝
      由于差集是基于顺序表的删除操作,即将被删除位后面的元素整体移动。所以再进行下个操作时表必须得恢复到原来的状态。设置暂存表,直接赋值eg:Ltemp=LA 这个是浅拷贝。结构里面值类型的成员都被赋给相同的值,但是对于指针类型的变量,只是复制了地址。
    解决:
      自定义赋值函数,把指针变量手动复制相应的内存
  • status 返回值,对于需求更改时很有用
  • 注意程序健壮性和可读性
#include<iostream>
#include <algorithm>
using namespace std;

//预定义常量和类型
#define MAXSIZE 1000
#define ERROR 0
#define OK 1
#define SqList_overflow -2
typedef int Status;
typedef int ElemType;

//定义线性表的结构体
struct SqList
{
	int length;
	ElemType* e;
};

//初始化顺序表
Status init(SqList&);
//给顺序表赋值
void read(SqList&);
//显示顺序表
void display(SqList&);
//按值检索元素
Status searchSame(ElemType,SqList&);
//A表删掉跟B表相同的元素
Status deleteElem(int, SqList&);
//添加元素
Status insert(ElemType , SqList& );
//copy
void copy(SqList&, SqList&);

//交
void jiao1(SqList&, SqList&);
Status jiao(SqList&, SqList&, SqList&);
//差
void cha1(SqList&, SqList&);
Status cha(SqList&, SqList&);
//并
Status bing(SqList&, SqList&);

//菜单
void menu();
//判断选择并处理
void check_chocie( SqList& L, SqList&);
//判断status并处理
void check_status(Status);
//测试过程
void test();

int main() {	
	 //交:建立C表,遍历A表的所有元素,找出跟B表相同的元素,把所得元素赋给C表	   	   
	 //差:建立C表,选择A-B还是B—A,eg遍历A表--在B表中找出两个表相同的元素,每找到一个就删掉一个,A剩下的元素赋给C	   	   
	 //并:建立C表,遍历A,如果没有在B出现过,就加在B表里面
	//注意差和并,操作完成之后要对AB进行恢复
	test();
}
void test() {
	//根据用户输入建立两个顺序表
	SqList LA, LB;
	//初始化顺序表
	check_status(init(LA));
	check_status(init(LB));
	//给顺序表赋值
	cout << "A 表:";
	read(LA);
	cout << "A 表: ";
	display(LA);
	cout << "B 表 :";
	read(LB);
	cout << "B 表: ";
	display(LB);

	//显示菜单,交并差三个操作
	menu();
	check_chocie(LA, LB);
}
void check_status(Status m) {
	if (m == 0 || m == -2) return;
}
Status init(SqList& L) {
	L.e = new ElemType[MAXSIZE];
	if (L.e == NULL) {
		cout << "存储空间分配失败" << endl;
		return SqList_overflow;
	}
	L.length = 0;
	//cout << "初始化顺序表成功" << endl;
	return OK;
}
void read(SqList& L) {
	int m;
	for (;;) {
		cout << "请输入顺序表的元素个数m:" << endl;
		cin >> m;
		if (m < 0) {
			cout << "请输入合法的顺序表的元素个数m:" << endl;
		}
		else break;
	}
	for (int i = 0; i < m; i++) {
		cin >> L.e[i];
		L.length++;
	}
}
void display(SqList& L) {
	for (int i = 0; i < L.length; i++) {
		cout << L.e[i] << "," ;		
	}
	if (L.length == 0) {
		cout << "表为空" << endl;
	}
	cout << endl;
}
void menu() {
	cout << endl;
	cout << "1812030065  李诗雨" << endl;
	cout << "1-------求两线性表的交集" << endl;
	cout << "2-------求两线性表的差集" << endl;
	cout << "3-------求两线性表的并集" << endl;

}
void check_chocie(SqList& LA, SqList&LB) {
	int n;
	for (;;) {
		cout << "请输入操作代码" << endl;
		cout << "        输入负数退出" << endl;
		cin >> n;
		if (n >= 1 && n <= 3) {
			switch (n)
			{
			case 1:jiao1(LA, LB);
				break;
			case 2:cha1(LA, LB);
				break;
			case 3:check_status(bing(LA, LB));
				break;
			}
		}
		else if (n < 0) {
			return;
		}
		else {
			cout << "请输入正确操作码" << endl;
		}
	}    
	
}
//交
void jiao1(SqList& LA, SqList& LB) {
	SqList LC;
	check_status(init(LC));

	check_status(jiao(LA,LB,LC));

	cout << "A和B交集的结果是:" << endl;
	display(LC);
}
Status jiao(SqList&LA, SqList&LB, SqList& LC) {
	for (int i = 0; i < LA.length; i++) {
		if (searchSame(LA.e[i], LB)) {
			LC.e[LC.length] = LA.e[i];
			LC.length++;
		}
	}
	return OK;
}
Status searchSame(ElemType elem, SqList& L) {
	for (int i = 0; i < L.length; i++) {
		if (elem == L.e[i]) {
			return OK;
		}
	}
	return ERROR;
}

void copy(SqList& L1, SqList& L2) {
	L1.length = L2.length;
	for (int i = 0; i < L2.length; i++) {
		L1.e[i] = L2.e[i];
	}
}
//差
void cha1(SqList& LA, SqList& LB) {
	int m;
	SqList Ltemp;
	check_status(init(Ltemp));
	SqList LC;
	check_status(init(LC));
	for (;;) {
		cout << "选择A-B,请输入1,选择B—A请输入2" << endl;
		cin >> m;
		if (m == 1 || m == 2) {
			break;
		}
		else {
			cout << "请输入合法的数m:" << endl;
		}
	}
	if (m == 1) {
		copy(Ltemp, LA);
		check_status(cha(LA, LB));
		LC = LA;
		cout << "A-B 结果是:" << endl;
		display(LC);
		copy(LA, Ltemp);
	}
	else {
		copy(Ltemp, LB);
		check_status(cha(LB, LA));
		LC = LB;
		cout << "B-A 结果是:" << endl;
		display(LC);
		copy(LB, Ltemp);
	}
}
Status cha(SqList& LA, SqList& LB) {
	for (int i = 0; i < LA.length; i++) {
		if (searchSame(LA.e[i], LB)) {
			check_status(deleteElem(i, LA));
			i--;
		}
	}
	return OK;
}
Status deleteElem(int p, SqList& L) {
	for (int i = p; i < L.length ; i++) {
		L.e[i] = L.e[i + 1];
	}
	L.length--;
	return OK;
}
Status insert(ElemType e, SqList&L) {
	if (L.length == MAXSIZE)
	{
		cout << "存储空间已满" << endl;
		return ERROR;
	}
	L.e[L.length] = e;
	L.length++;
	return OK;
}
//并
Status bing(SqList& LA, SqList& LB) {

	SqList LC;
	check_status(init(LC));
	SqList Ltemp;
	check_status(init(Ltemp));
	copy(Ltemp, LB);

	for (int i = 0; i < LA.length; i++) {
		if (!(searchSame(LA.e[i], LB))) {
			insert(LA.e[i], LB);
		}
	}
	LC = LB;

	cout << "A和B并集的结果是:" << endl;
	display(LC);
	copy(LB, Ltemp);
	return OK;
}

结果:
顺序表实现两个集合的交集,差集,并集

单链表的操作

单链表的基本操作

#include<iostream>
using namespace std;
//预定义常量和类型
#define OK 1;
#define ERROR 0;

typedef int Status;
typedef int ElemType;

//单链表的存储结构定义
struct LNode {
	ElemType data;//数据域
	LNode* next;//指针域
};
typedef LNode* LinkList;//LinkList为LNode类型的指针
//初始化一个链表:生成新结点作头结点,用头指针L指向头结点。头结点的指针域置空。
void init(LinkList& L);
//给单链表赋值 :用指针p指向第一个结点,给结点数据域赋值
void read(LinkList& L);
//menu
void menu();
//选择操作码
void check_n(int n, LinkList& L);
//销毁单链表: 释放所有结点和头指针
void destory(LinkList& L);
//清空单链表L:释放数据元素,保留头节点并将头节点指针域置空
Status clear(LinkList& L);
//求单链表L的长度 :用指针p指向第一个结点,遍历链表,统计结点个数
void getLength(LinkList& L);
//判断单链表L是否为空 :判断第一个结点是否为空
void check_null(LinkList& L);
//获取单链表L中的某个数据元素内容:先判断输入位置m是否小于0,
//遍历结点当遍历到第m时输出当前结点的内容,如果遍历完说明超出链表长度
Status getData(LinkList& L);
//检索值为e的数据元素
Status searchData(LinkList& L);
//在单链表L中插入一个数据元素
Status insertNode(LinkList& L);
//删除单链表L中第i个数据
Status deleteNode(LinkList& L);
//判断status
void Status_check(Status n, LinkList& L);
//显示链表
void display(LinkList& L);
void bing();
void test();

int main() {
	test();
}

void init(LinkList& L){
	L = new LNode;
	L->next = NULL;  
}
void read(LinkList& L) {
	int m;//把m个元素放入顺序表
	for (;;) {
		cout << "请输入单链表的元素个数m:" << endl;
		cin >> m;
		if (m < 0) {
			cout << "请输入合法的单链表的元素个数m:" << endl;
		}
		else break;
	}
	LinkList p;
	p = L;//p 是头节点地址
	for (int i = 0; i < m; i++) {
		LinkList s;
		s = new LNode;
		s->next = NULL;
		cin >> s->data;//创建新的结点,赋值
		p->next = s;//p 指向结点 s
		p = p->next;
	}
	display(L);
}
void menu() {
	cout << endl;
	cout << "1812030065  李诗雨" << endl;
	cout << "1-------初始化单链表L" << endl;
	cout << "2-------销毁单链表L" << endl;
	cout << "3-------清空单链表L" << endl;
	cout << "4-------求单链表L的长度" << endl;
	cout << "5-------判断单链表L是否为空" << endl;
	cout << "6-------获取单链表L中的某个数据元素内容" << endl;
	cout << "7-------检索值为e的数据元素" << endl;
	cout << "8-------在单链表L中插入一个数据元素" << endl;
	cout << "9-------删除单链表L中第i个数据" << endl;
}
void check_n(int n,LinkList&L) {
	//不要忘了每个case里都要break
	switch (n)
	{
	case 1:
		init(L);
		break;
	case 2:
		destory(L);
		break;
	case 3:
		Status_check(clear(L), L);
		break;
	case 4:
		getLength(L);
		break;
	case 5:
		check_null(L);
		break;
	case 6:
		Status_check(getData(L), L);
		break;
	case 7:
		Status_check(searchData(L), L);
		break;
	case 8:
		Status_check(insertNode(L), L);
		break;
	case 9:
		Status_check(deleteNode(L), L);
		break;
	default:
		break;
	}

	
}
void destory(LinkList& L) {
	LinkList p;
	while (L) {
		p = L;
		L = L->next;
		delete p;
	}
	cout << "链表已销毁" << endl;
}
Status clear(LinkList& L) {
	LinkList p,q;
	p = L->next;
	while (p)
	{
		q = p;
		p = p->next;
		delete q;	
	}
	L->next = NULL;
	cout << "链表已清空" << endl;
	return OK;
}
void getLength(LinkList& L) {
	LinkList p = L->next;
	int count = 0;
	while (p)
	{
		count++;
		p = p->next;
	}
	cout << "链表的长度为:" << count << endl;
}
void check_null(LinkList& L) {
	if (!L->next) {
		cout << "该链表为空" << endl;
	}
	else
	{
		cout << "该链表不为空" << endl;
	}
}
Status getData(LinkList& L) {
	int m;
	cout << "请输入要获取第几个结点的内容" << endl;
	cin >> m;
	while (m<=0)
	{
		cout << "不合法,请重新输入要获取第几个结点的内容" << endl;
		cin >> m;
	}
	LinkList p = L->next;
	int count=0;
	while (p)
	{
		count++;
		if (m == count) {
			cout << "结点的内容: " << p->data << endl;
			return OK;			
		}
		p = p->next;		
	}

		cout << "ERROR:超过链表长度!" << endl;
		return ERROR;
	
}
Status searchData(LinkList& L) {
	ElemType e;
	cout << "请输入要检索的数据:" << endl;
	cin >> e;
	LinkList p = L->next;//p 指向第一个结点
	int count = 0;
	while (p)
	{
		count++;
		if (p->data == e) {
			cout << "结点的位置: " << count << endl;
			return OK;
		}
		p = p->next;
	}
	cout << "ERROR:没有检索到该元素" << endl;
	return ERROR;

}
Status insertNode(LinkList& L) {
	int m;
	cout << "请输入要插入到第几个结点" << endl;
	cin >> m;
	while (m <= 0)
	{
		cout << "不合法,请重新输入要插入到第几个结点" << endl;
		cin >> m;
	}
	LinkList p = L->next;
	int count = 0;
	while (p)
	{
		count++;
		if (m-1 == count) {
			LinkList s;
			s = new LNode;
			cout << "请输入要插入的数据内容" << endl;
			cin >> s->data;
			s->next = p->next;
			p->next = s;
			return OK;
		}
		p = p->next;
	}

	cout << "ERROR:超过链表长度!" << endl;
	return ERROR;
}
Status deleteNode(LinkList& L) {
	int m;
	cout << "请输入要删除第几个结点" << endl;
	cin >> m;
	while (m <= 0)
	{
		cout << "不合法,请重新输入要删除第几个结点" << endl;
		cin >> m;
	}
	LinkList p = L->next;
	int count = 0;
	while (p)
	{
		count++;
		if (m - 1 == count) {
			LinkList s;
			s = p->next;
			p->next=s->next;
			delete s;
			cout << "已删除该结点" << endl;
			return OK;
		}
		p = p->next;
	}
	cout << "ERROR:超过链表长度!" << endl;
	return ERROR;
}
void Status_check(Status n,LinkList&L) {
	if (n == 1) {
		display(L);
	}
}
void display(LinkList& L) {
	LinkList p = L->next;//p 指向第一个结点
	cout << "链表更新为:" << endl;
	if (!p) {
		cout << "链表为空" << endl;
		return;
	}
	while (p)
	{
		ElemType e = p->data;
		cout << e << "," ;
		p = p->next;
	}
	cout << endl;
}
void test() {
	//初始化一个单链表
	LinkList L;
	init(L);
	cout << "单链表初始化成功!" << endl;
	//给顺序表赋值
	read(L);
	int n;
	for (;;) {
		//显示菜单
		menu();
		//输入操作码
		for (;;) {
			cout << "请输入操作代码" << endl;
			cout << "        输入负数退出" << endl;
			cin >> n;			
			//根据操作码选择操作
			if (n >= 1 && n <= 9) {								
					check_n(n, L);				
			}
			else if (n < 0) {
				return;
			}
			else {
				cout << "请输入正确操作码" << endl;
			}
		}
	}
	
}


//(6)设计一个算法,通过一趟遍历在单链表中确定值最大的结点。

// 假设第一个结点中数据是最大值,依次与下一个元素比较,
//若其小于下一个元素,则设其下一个元素为最大值,反复进行比较,直到遍历完该链表。
ElemType Max(LinkList L) {
	if (L->next == NULL) return NULL;
	LinkList pmax, p;
	pmax = L->next; //假定第一个结点中数据是最大值
	p = L->next->next;//p 指向第二个结点
	while (p != NULL) {//如果下一个结点存在
		if (p->data > pmax->data) pmax = p;//如果p的值大于pmax的值,则重新赋值
		p = p->next;//遍历链表
	}
	return pmax->data;
}

	//(7)设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的存储空间。
	//从首元结点开始,逐个地把链表L的当前结点p插入新的链表头部。
	void  inverse(LinkList & L)
	{// 逆置带头结点的单链表 L
		LinkList p, q;
		p = L->next;  L->next = NULL;
		while (p) {
			q = p->next;    // q指向*p的后继
			p->next = L->next;
			L->next = p;       // *p 插入在头结点之后
			p = q;
		}
	}

	

单链表的基本操作结果1
单链表的基本操作结果2
单链表的基本操作结果3

遇到的问题与解决

  • 问题:访问权限冲突:cout << p->data << “,” ;
    解决:调试查看p发现while(p)p0xcdcdcdcd:data=???next=???
    输入为0时,p值是0 说明最后一个结点的next不是null
    是read里面新建结点没有给结点的next赋值null。。。应该用init的

求两个有序单链表的并集

两种算法求求两个有序单链表的并集
我用的是新建链表,新建结点复制数据来避免获取上一个结点指针的麻烦

#include<iostream>
using namespace std;
//预定义常量和类型
#define OK 1;
#define ERROR 0;

typedef int Status;
typedef int ElemType;

//单链表的存储结构定义
struct LNode {
	ElemType data;//数据域
	LNode* next;//指针域
};
typedef LNode* LinkList;//LinkList为LNode类型的指针
//初始化一个链表:生成新结点作头结点,用头指针L指向头结点。头结点的指针域置空。
void init(LinkList& L);
//给单链表赋值 :用指针p指向第一个结点,给结点数据域赋值
void read(LinkList& L);
void display(LinkList& L);
void bing();

int main() {
	bing();
}
void display(LinkList& L) {
	LinkList p = L->next;//p 指向第一个结点
	cout << "链表:" << endl;
	if (!p) {
		cout << "链表为空" << endl;
		return;
	}
	while (p)
	{
		ElemType e = p->data;
		cout << e << ",";
		p = p->next;
	}
	cout << endl;
}
void read(LinkList& L) {
	int m;//把m个元素放入顺序表
	for (;;) {
		cout << "请输入单链表的元素个数m:" << endl;
		cin >> m;
		if (m < 0) {
			cout << "请输入合法的单链表的元素个数m:" << endl;
		}
		else break;
	}
	LinkList p;
	p = L;//p 是头节点地址
	for (int i = 0; i < m; i++) {
		LinkList s;
		s = new LNode;
		s->next = NULL;
		cin >> s->data;//创建新的结点,赋值
		p->next = s;//p 指向结点 s
		p = p->next;
	}
	display(L);
}
void init(LinkList& L) {
	L = new LNode;
	L->next = NULL;
}
//两个有序单链表的归并
void bing() {
	cout << "请输入有序表A" << endl;
	LinkList LA;
	init(LA);
	read(LA);
	cout << "请输入有序表B" << endl;
	LinkList LB;
	init(LB);
	read(LB);
	LinkList LC;
	init(LC);
	LinkList pa, pb, pc;
	pa = LA->next;
	pb = LB->next;
	pc = LC;
	//当两个表没有一个到表尾时
	while (pa && pb) {
		LinkList s;
		s = new LNode;
		//给LC新建结点,把两表中较小的结点数据域内容复制一份
		if (pa->data < pb->data) {
			s->data = pa->data;
			pa = pa->next;
		}
		else if (pa->data > pb->data) {
			s->data = pb->data;
			pb = pb->next;
		}
		else {
			//相等时,把A表的数据复制过来,把B表的这个数据跳过去
			s->data = pa->data;
			pa = pa->next;
			pb = pb->next;
		}
		s->next = NULL;
		pc->next = s;
		pc = pc->next;
	}
	if (pa) {
		pc->next = pa;
	}
	else {
		pc->next = pb;
	}
	cout << "结果 C";
	display(LC);
	cout << "181203065 李诗雨" << endl;
}

两个有序单链表求并集

遇到的问题

有点晕指针。报错之后重点检查指针再看逻辑,然后再看调试。

栈和队列的操作

栈的链式存储结构

#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
typedef int Status;
typedef char ElemType;

//链栈的存储结构
struct StackNode {
	ElemType data;
	StackNode* next;
};
typedef StackNode* ListStack;
//初始化
Status InitStack(ListStack&);
//入栈
Status Push(ListStack&, ElemType);
void Push(ListStack& );
//出栈
Status Pop(ListStack&, ElemType&);
void Pop(ListStack& );
//取栈顶元素
Status QuZhanDing(ListStack&, ElemType&);
void QuZhanDing(ListStack& );
//检查状态
void CheckStatus(Status);
//判断回文
void CheckPalindrome();
//菜单
void Menu();
void CheckN(int,ListStack& );
int main() {
	ListStack S;
	CheckStatus(InitStack(S));//构造一个空栈
	int n;
	for (;;) {
		//显示菜单
		Menu();
		//输入操作码
		for (;;) {
			cout << "请输入操作代码" << endl;
			cout << "        输入负数退出" << endl;
			cin >> n;
			if (n >= 1 && n <= 3) {
				//根据操作码选择操作
				CheckN(n,S);
			}
			else if (n < 0) {
				return 0;
			}
			else {
				cout << "请输入正确操作码" << endl;
			}
		}
	}
	
}
Status InitStack(ListStack& S) {
	S = NULL;//栈顶指针置为空
	return OK;
}
Status QuZhanDing(ListStack& S, ElemType&Se)
{
	if (S == NULL) return ERROR;//判断栈是否为空
	Se = S->data;               //将栈顶元素赋给se,栈顶指针不变
}
void QuZhanDing(ListStack& S) {
	ElemType Se;
	CheckStatus( QuZhanDing(S, Se));
	cout << "栈顶元素:" << Se << endl;

}
void CheckStatus(Status x) {
	if (x == 0) cout << "ERROR\n";
	return;
}
Status Push(ListStack& S, ElemType e) {
	ListStack p = new StackNode;//生成一个新结点
	p->data = e;//将新结点数据域置为e
	p->next = S;//将新节点插入栈顶
	S = p;//修改栈顶指针为p
	return OK;
}
void Push(ListStack& S) {
	ElemType e;
	cout << "请输入入栈字符" << endl;
	cin >> e;
	CheckStatus(Push(S, e));
}
Status Pop(ListStack& S, ElemType& Se) {
	if (S == NULL) return ERROR;//判断栈是否为空
	Se = S->data;               //将栈顶元素赋给se
	ListStack p = S;            //临时保存栈顶元素的空间以备释放
	S = p->next;                //修改栈顶指针,指向新的栈顶元素
	delete p;                   //释放原栈顶元素的空间
	return OK;
}
void Pop(ListStack& S) {
	ElemType Se;
	CheckStatus(Pop(S, Se));
	cout << "出栈元素为" << Se << endl;
}
void Menu() {
	cout << endl;
	cout << "1812030065  李诗雨" << endl;
	cout << "1-------入栈" << endl;
	cout << "2-------出栈" << endl;
	cout << "3-------取栈顶元素" << endl;
	cout << "4-------判断回文" << endl;	
}

void CheckN(int n,ListStack& S) {
	switch (n)
	{
	case 1: Push(S);break;
	case 2:Pop(S); break;
	case 3:QuZhanDing(S); break;
	case 4:CheckPalindrome(); break;
	default:
		break;
	}
}

void CheckPalindrome() {
	ListStack S;
	CheckStatus(InitStack(S));//构造一个空栈
	string str;
	cout << "请输入测试字符串" << endl;
	cin >> str;
	if (str.length() % 2 == 0) {
		for (int i = 0; i < str.length() / 2; i++) {
			CheckStatus(Push(S, str[i])); //把一半的字符入栈
		}
		for (int i = str.length() / 2; i < str.length(); i++) {
			ElemType e;
			CheckStatus(Pop(S, e));
			if (e != str[i]) {
				cout << "不是回文数" << endl;
				return;
			}
		}
		
	}
	else {
		for (int i = 0; i < str.length() / 2; i++) {
			CheckStatus(Push(S, str[i])); //把一半的字符入栈
		}
		for (int i = str.length() / 2+1; i < str.length(); i++) {
			//出栈元素和剩下的字符比对,如果有不同的就不是回文数
			ElemType e;
			CheckStatus(Pop(S, e));
			if (e != str[i]) {
				cout << "不是回文数" << endl;
				return;
			}
		}
	}
	cout << "是回文数" << endl;

}

链栈1
链栈2

栈的顺序存储结构

#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define MAXSIZE 1000
typedef int Status;
typedef char ElemType;


//顺序栈的存储结构
struct ListStack {
	//存储空间的基地址
	ElemType* base;
	//栈顶指针
	ElemType* top;
	//最大容量
	int StackSize;

};
//初始化
Status InitStack(ListStack&);
//入栈
Status Push(ListStack&, ElemType);
void Push(ListStack&);
//出栈
Status Pop(ListStack&, ElemType&);
void Pop(ListStack& );
//取栈顶元素
Status QuZhanDing(ListStack&, ElemType&);
void QuZhanDing(ListStack& );
//检查状态
void CheckStatus(Status);
//菜单
void Menu();
void CheckN(int, ListStack&);

int main() {
	ListStack S;
	CheckStatus(InitStack(S));//构造一个空栈
	int n;
	for (;;) {
		//显示菜单
		Menu();
		//输入操作码
		for (;;) {
			cout << "请输入操作代码" << endl;
			cout << "        输入负数退出" << endl;
			cin >> n;
			if (n >= 1 && n <= 3) {
				//根据操作码选择操作
				CheckN(n, S);
			}
			else if (n < 0) {
				return 0;
			}
			else {
				cout << "请输入正确操作码" << endl;
			}
		}
	}
}
Status InitStack(ListStack& S) {
	//构造一个空栈
	//为顺序栈动态分配一个最大容量为MAXSIZE的数组空间,使base指向这段空间的基地址,即栈底
	S.base = new ElemType[MAXSIZE];
	if (!S.base) return ERROR;//存储空间分配失败
	S.top = S.base;//栈顶指针置为base,空栈
	S.StackSize = MAXSIZE;//栈的最大容量为MAXSIZE
	return OK;
}
Status QuZhanDing(ListStack& S, ElemType& Se)
{
	if (S.top==S.base) return ERROR;//判断栈是否为空
	Se = *(S.top-1;               //将栈顶元素赋给se,栈顶指针不变
}
void QuZhanDing(ListStack& S) {
	ElemType Se;
	CheckStatus(QuZhanDing(S, Se));
	cout << "栈顶元素:" << Se << endl;

}
void CheckStatus(Status x) {
	if (x == 0) cout << "ERROR\n";
	return;
}
Status Push(ListStack& S, ElemType e) {
	if (S.top -S.base==S.StackSize) return ERROR;//判断是否栈满
	*S.top++ = e;//先把e压入栈,栈顶指针加1
	return OK;
}
void Push(ListStack& S) {
	ElemType e;
	cout << "请输入入栈字符" << endl;
	cin >> e;
	CheckStatus(Push(S, e));
}
Status Pop(ListStack& S, ElemType& Se) {
	if (S.top == S.base) return ERROR;//判断栈是否为空
	Se = *--S.top;//栈顶指针减1,将栈顶元素赋给Se
	return OK;
}
void Pop(ListStack& S) {
	ElemType Se;
	CheckStatus(Pop(S, Se));
	cout << "出栈元素为" << Se << endl;
}
void Menu() {
	cout << endl;
	cout << "1812030065  李诗雨" << endl;
	cout << "1-------入栈" << endl;
	cout << "2-------出栈" << endl;
	cout << "3-------取栈顶元素" << endl;
}
void CheckN(int n, ListStack& S) {
	switch (n)
	{
	case 1: Push(S); break;
	case 2:Pop(S); break;
	case 3:QuZhanDing(S); break;
	default:
		break;
	}
}

队列

队列的顺序结构

#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define MAXQSIZE 1000
typedef int Status;
typedef char ElemType;

//顺序循环队列的存储结构
struct ListQueue {
	//存储空间的基地址
	ElemType* base;
	//头指针和尾指针
	int  front;
	int rear;
};

//队列初始化
Status InitQueue(ListQueue&);
//入队
Status EnQueue(ListQueue&, ElemType&);
void EnQueue(ListQueue&);
//出队
Status DeQueue(ListQueue&, ElemType&);
void DeQueue(ListQueue&);
//取队头元素
Status GetHead(ListQueue&, ElemType&);
void GetHead(ListQueue&);
//求队长度
void QueueLength(ListQueue&);
//菜单
void Menu();
//检查n
void CheckN(int, ListQueue&);
//检查状态
void CheckStatus(Status);

int main() {
	ListQueue Q;
	CheckStatus(InitQueue(Q));//构造一个空队
	int n;
	for (;;) {
		//显示菜单
		Menu();
		//输入操作码
		for (;;) {
			cout << "请输入操作代码" << endl;
			cout << "        输入负数退出" << endl;
			cin >> n;
			if (n >= 1 && n <= 4) {
				//根据操作码选择操作
				CheckN(n, Q);
			}
			else if (n < 0) {
				return 0;
			}
			else {
				cout << "请输入正确操作码" << endl;
			}
		}
	}
}

Status InitQueue(ListQueue& Q) {
	//为队列分配一个最大容量为MAXQSIZE的数组空间
	Q.base = new ElemType[MAXQSIZE];
	//存储分配失败
	if (!Q.base) return ERROR;
	//头指针和尾指针置为0,队列为空
	Q.rear = Q.front = 0;
	return OK;
}
Status EnQueue(ListQueue& Q, ElemType& e) {
	//插入元素e为新的队尾元素
	//尾指针在循环意义上加1等于头指针表示队满
	if ((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR;
	//新元素加入队尾
	Q.base[Q.rear] = e;
	//尾指针加1
	Q.rear = (Q.rear + 1) % MAXQSIZE;
	return OK;
}
void EnQueue(ListQueue& Q) {
	ElemType e;
	cout << "请输入入队元素" << endl;
	cin >> e;
	CheckStatus(EnQueue(Q, e));
}
Status DeQueue(ListQueue& Q, ElemType& e) {
	//删除Q的队头元素,用e返回其值
	//是否队空
	if (Q.rear == Q.front) return ERROR;
	//保存队头元素
	e = Q.base[Q.front];
	//头指针加1
	Q.front = (Q.front + 1) % MAXQSIZE;
	return OK;
}
void DeQueue(ListQueue& Q) {
	ElemType e;
	CheckStatus(DeQueue(Q, e));
	cout << "出队元素:" << e << endl;
}
Status GetHead(ListQueue& Q, ElemType& e) {
	//取Q的队头元素,用e返回其值
	//是否队空
	if (Q.rear == Q.front) return ERROR;
	//保存队头元素
	e = Q.base[Q.front];
	return OK;
}
void GetHead(ListQueue& Q) {
	ElemType e;
	CheckStatus(GetHead(Q, e));
	cout << "队头元素:" << e << endl;
}
void QueueLength(ListQueue& Q) {
	cout << "队列长度为:" << (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE << endl;
}
void Menu() {
	cout << endl;
	cout << "1812030065  李诗雨" << endl;
	cout << "1-------入队" << endl;
	cout << "2-------出队" << endl;
	cout << "3-------取队头元素" << endl;
	cout << "4-------求队列长度" << endl;
}
void CheckN(int n, ListQueue& Q) {
	switch (n)
	{
	case 1:EnQueue(Q); break;
	case 2:DeQueue(Q); break;
	case 3:GetHead(Q); break;
	case 4:QueueLength(Q); break;
	default:
		break;
	}
}
void CheckStatus(Status x) {
	if (x == 0) cout << "ERROR\n";
	return;
}

队列的链式存储结构

#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define MAXQSIZE 1000
typedef int Status;
typedef char ElemType;

//链式队列的存储结构
struct QueueNode {
	ElemType data;
	QueueNode* next;
};
struct LinkQueue {
	QueueNode* front;
	QueueNode* rear;
	int QueueLength=0;
};
//队列初始化
Status InitQueue(LinkQueue&);
//入队
Status EnQueue(LinkQueue&, ElemType&);
void EnQueue(LinkQueue&);
//出队
Status DeQueue(LinkQueue&, ElemType&);
void DeQueue(LinkQueue&);
//取队头元素
Status GetHead(LinkQueue&, ElemType&);
void GetHead(LinkQueue&);
//求队长度
void QueueLength(LinkQueue&);
//菜单
void Menu();
//检查n
void CheckN(int, LinkQueue&);
//检查状态
void CheckStatus(Status);

int main() {
	LinkQueue Q;
	CheckStatus(InitQueue(Q));//构造一个空队
	int n;
	for (;;) {
		//显示菜单
		Menu();
		//输入操作码
		for (;;) {
			cout << "请输入操作代码" << endl;
			cout << "        输入负数退出" << endl;
			cin >> n;
			if (n >= 1 && n <= 4) {
				//根据操作码选择操作
				CheckN(n, Q);
			}
			else if (n < 0) {
				return 0;
			}
			else {
				cout << "请输入正确操作码" << endl;
			}
		}
	}
}

Status InitQueue(LinkQueue& Q) {
	//构造一个空队列Q
	//生成新的结点作为头节点,队列的头指针和尾指针都指向该结点
	Q.front = Q.rear = new QueueNode;
	//头节点的指针域置为空
	Q.front->next = NULL;
	return OK;
}
Status EnQueue(LinkQueue& Q, ElemType& e) {
	//为入队元素分配结点空间,用指针p指向
	QueueNode* p = new QueueNode;
	p->data = e;//将新结点数据置为e
	p->next = NULL;
	Q.rear->next = p;//将新结点插入到队尾
	Q.rear = p;//修改队尾指针
	Q.QueueLength++;
	return OK;
}
void EnQueue(LinkQueue& Q) {
	ElemType e;
	cout << "请输入入队元素" << endl;
	cin >> e;
	CheckStatus(EnQueue(Q, e));
}
Status DeQueue(LinkQueue& Q, ElemType& e) {
	//是否队空
	if (Q.rear == Q.front) return ERROR;
	//临时保存队头元素空间以备释放
	//p 指向队头元素
	QueueNode* p;
	p = Q.front->next;
    //e 保存队头元素的值
	e = p->data;
	//修改头指针的指针域,指向下一个结点
	Q.front->next = p->next;
	//如果最后一个元素被删,队尾指针指向头节点
	if (Q.rear == p) Q.rear = Q.front;
	delete p;//释放原队头元素的空间
	Q.QueueLength--;
	return OK;	
}
void DeQueue(LinkQueue& Q) {
	ElemType e;
	CheckStatus(DeQueue(Q, e));
	cout << "出队元素:" << e << endl;
}
Status GetHead(LinkQueue& Q, ElemType& e) {
	//取Q的队头元素,用e返回其值
	//是否队空
	if (Q.rear == Q.front) return ERROR;
	//保存队头元素
	e = Q.front->next->data;
	return OK;
}
void GetHead(LinkQueue& Q) {
	ElemType e;
	CheckStatus(GetHead(Q, e));
	cout << "队头元素:" << e << endl;
}
void QueueLength(LinkQueue& Q) {
	cout << "队列长度为:" << Q.QueueLength << endl;
}
void Menu() {
	cout << endl;
	cout << "1812030065  李诗雨" << endl;
	cout << "1-------入队" << endl;
	cout << "2-------出队" << endl;
	cout << "3-------取队头元素" << endl;
	cout << "4-------求队列长度" << endl;
}
void CheckN(int n, LinkQueue& Q) {
	switch (n)
	{
	case 1:EnQueue(Q); break;
	case 2:DeQueue(Q); break;
	case 3:GetHead(Q); break;
	case 4:QueueLength(Q); break;
	default:
		break;
	}
}
void CheckStatus(Status x) {
	if (x == 0) cout << "ERROR\n";
	return;
}

带头节点不带头指针的循环链队

(6)假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素站点(注意不设头指针) ,试编写相应的置空队、判队空 、入队和出队等算法。
[题目分析]
置空队就是建立一个头节点,并把头尾指针都指向头节点,头节点是不存放数据的;判队空就是当头指针等于尾指针时,队空;入队时,将新的节点插入到链队列的尾部,同时将尾指针指向这个节点;出队时,删除的是队头节点,要注意队列的长度大于1还是等于1的情况,这个时候要注意尾指针的修改,如果等于1,则要删除尾指针指向的节点。


//(6)假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素站点(注意不设头指针) ,
//试编写相应的置空队、判队空 、入队和出队等算法。
//[题目分析]
//置空队就是建立一个头节点,并把头尾指针都指向头节点,头节点是不存放数据的;
//判队空就是当头指针等于尾指针时,队空;入队时,将新的节点插入到链队列的尾部,
//同时将尾指针指向这个节点;出队时,删除的是队头节点,要注意队列的长度大于1还是等于1的情况,
//这个时候要注意尾指针的修改,如果等于1,则要删除尾指针指向的节点。

#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define MAXQSIZE 1000
typedef int Status;
typedef char ElemType;

//链式队列的存储结构
struct QueueNode {
	ElemType data;
	QueueNode* next;
};
struct LinkQueue {
	QueueNode* rear;
};
//队列初始化
Status InitQueue(LinkQueue&);
//入队
Status EnQueue(LinkQueue&, ElemType&);
void EnQueue(LinkQueue&);
//出队
Status DeQueue(LinkQueue&, ElemType&);
void DeQueue(LinkQueue&);
//置空队
void ClearQueue(LinkQueue&);
//判断队空
void CheckNull(LinkQueue&);

//菜单
void Menu();
//检查n
void CheckN(int, LinkQueue&);
//检查状态
void CheckStatus(Status);

int main() {
	LinkQueue Q;
	CheckStatus(InitQueue(Q));//构造一个空队
	int n;
	for (;;) {
		//显示菜单
		Menu();
		//输入操作码
		for (;;) {
			cout << "请输入操作代码" << endl;
			cout << "        输入负数退出" << endl;
			cin >> n;
			if (n >= 1 && n <= 4) {
				//根据操作码选择操作
				CheckN(n, Q);
			}
			else if (n < 0) {
				return 0;
			}
			else {
				cout << "请输入正确操作码" << endl;
			}
		}
	}
}

Status InitQueue(LinkQueue& Q) {
	//构造一个空队列Q
	//生成新的结点作为头节点,队列的尾指针都指向该结点
	 Q.rear = new QueueNode;
	//头节点的指针域置为头节点地址
	Q.rear->next = Q.rear;
	return OK;
}
void ClearQueue(LinkQueue& Q) {
	QueueNode* p;
	//将队尾指针指向头节点
	Q.rear = Q.rear->next;
	//当队列非空时,将队列中的元素逐个删除
	while (Q.rear!=Q.rear->next)
	{
		p = Q.rear->next;
		Q.rear->next = p->next;
		delete p;
	}
}
void CheckNull(LinkQueue& Q) {
	//头节点的next指向自己时为空
	if (Q.rear == Q.rear->next) {
		cout << " NULL" << endl;
	}
	else {
		cout << " NOT NULL" << endl;
	}
}
Status EnQueue(LinkQueue& Q, ElemType& e) {
	//为入队元素分配结点空间,用指针p指向
	QueueNode* p = new QueueNode;
	p->data = e;//将新结点数据置为e
	p->next = Q.rear->next;
	Q.rear->next = p;//将新结点插入到队尾
	Q.rear = p;//修改队尾指针
	return OK;
}
void EnQueue(LinkQueue& Q) {
	ElemType e;
	cout << "请输入入队元素" << endl;
	cin >> e;
	CheckStatus(EnQueue(Q, e));
}
Status DeQueue(LinkQueue& Q, ElemType& e) {
	//是否队空
	if (Q.rear == Q.rear->next) return ERROR;
	//把头节点之后的元素摘下
	//临时保存队头元素空间以备释放
	//p 指向队头元素
	QueueNode* p;
	p = Q.rear->next->next;
	//e 保存队头元素的值
	e = p->data;
	//修改头结点的指针域,指向下一个结点
	Q.rear->next->next = p->next;
	//如果最后一个元素被删,队尾指针指向头节点
	if (Q.rear == p) Q.rear = Q.rear->next;
	delete p;//释放原队头元素的空间
	return OK;
}
void DeQueue(LinkQueue& Q) {
	ElemType e;
	CheckStatus(DeQueue(Q, e));
	cout << "出队元素:" << e << endl;
}

void Menu() {
	cout << endl;
	cout << "1812030065  李诗雨" << endl;
	cout << "1-------入队" << endl;
	cout << "2-------出队" << endl;
	cout << "3-------置空队列" << endl;
	cout << "4-------判断队列是否为空" << endl;
}
void CheckN(int n, LinkQueue& Q) {
	switch (n)
	{
	case 1:EnQueue(Q); break;
	case 2:DeQueue(Q); break;
	case 3:ClearQueue(Q); break;
	case 4:CheckNull(Q); break;
	default:
		break;
	}
}
void CheckStatus(Status x) {
	if (x == 0) cout << "ERROR\n";
	return;
}

用tag标志来判断是队满还是队空

(7)假设以数组Q[m]存放循环队列中的元素, 同时设置一个标志tag,以tag == 0和tag == 1来区别在队头指针(front)和队尾指针(rear)相等时,队列状态为“空”还是“满”。试编写与此结构相应的插入(enqueue)和删除(dlqueue)算法。

#include <iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define MAXQSIZE 4
typedef int Status;
typedef char ElemType;

//顺序循环队列的存储结构
struct LinkQueue {
	//存储空间的基地址
	ElemType* base;
	//头指针和尾指针
	int  front;
	int rear;
	int tag;
};

//队列初始化
Status InitQueue(LinkQueue&);
//入队
Status EnQueue(LinkQueue&, ElemType&);
void EnQueue(LinkQueue&);
//出队
Status DeQueue(LinkQueue&, ElemType&);
void DeQueue(LinkQueue&);
//菜单
void Menu();
//检查n
void CheckN(int, LinkQueue&);
//检查状态
void CheckStatus(Status);

int main() {
	LinkQueue Q;
	CheckStatus(InitQueue(Q));//构造一个空队
	int n;
	for (;;) {
		//显示菜单
		Menu();
		//输入操作码
		for (;;) {
			cout << "请输入操作代码" << endl;
			cout << "        输入负数退出" << endl;
			cin >> n;
			if (n >= 1 && n <= 4) {
				//根据操作码选择操作
				CheckN(n, Q);
			}
			else if (n < 0) {
				return 0;
			}
			else {
				cout << "请输入正确操作码" << endl;
			}
		}
	}
}

Status InitQueue(LinkQueue& Q) {
	//为队列分配一个最大容量为MAXQSIZE的数组空间
	Q.base = new ElemType[MAXQSIZE];
	//存储分配失败
	if (!Q.base) return ERROR;
	//头指针和尾指针置为0,队列为空
	Q.rear = Q.front = 0; Q.tag = 0;
	return OK;
}
Status EnQueue(LinkQueue& Q, ElemType& e) {
	//插入元素e为新的队尾元素
	//尾指针等于头指针且tag=1表示队满
	if ((Q.rear == Q.front) && (Q.tag == 1))
	{
		cout << "队已满" << endl;
		return ERROR;
	}
	//新元素加入队尾
	Q.base[Q.rear] = e;
	//尾指针加1
	Q.rear = (Q.rear + 1) % MAXQSIZE;
	 if(Q.tag==0) Q.tag = 1;//队列已不空
	return OK;
}
void EnQueue(LinkQueue& Q) {
	ElemType e;
	cout << "请输入入队元素" << endl;
	cin >> e;
	CheckStatus(EnQueue(Q, e));
}
Status DeQueue(LinkQueue& Q, ElemType& e) {
	//删除Q的队头元素,用e返回其值
	//是否队空
	if (Q.tag == 0)
	{
		cout << "队空" << endl;
		return ERROR;
	}
	//保存队头元素
	e = Q.base[Q.front];
	//头指针加1
	Q.front = (Q.front + 1) % MAXQSIZE;
	if (Q.front == Q.rear) Q.tag = 0;//空队列
	return OK;
}
void DeQueue(LinkQueue& Q) {
	ElemType e;
	CheckStatus(DeQueue(Q, e));
	cout << "出队元素:" << e << endl;
}


void Menu() {
	cout << endl;
	cout << "1812030065  李诗雨" << endl;
	cout << "1-------入队" << endl;
	cout << "2-------出队" << endl;
	
}
void CheckN(int n, LinkQueue& Q) {
	switch (n)
	{
	case 1:EnQueue(Q); break;
	case 2:DeQueue(Q); break;
	default:
		break;
	}
}
void CheckStatus(Status x) {
	if (x == 0) cout << "ERROR\n";
	return;
}

问题与解决

  • #define MAXSIZSE 1000; 后面用的时候报错
    解决:宏定义是简单的文本替换 #define <宏名>  <字符串> ,所以是不能加 “ ;” 宏定义详解
  • *S.top++ = e; Se = *–S.top; 有点迷
    解决:复习一下想起来自增和自减若在后面就是等这一行所有运算都完成后进行,在前面的话优先级挺高了,比取值符 和数组的[]都高
int a[3] = { 1,2,3 };
	cout <<++a[1] ;

结果是 3

  • 注意参数用来返回值是引用传递而不是值传递
  • 循环队列里,队尾指针指向的是一个空单元
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

东西多了,后面编写好卡,见 数据结构(2)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值