数据结构-线性表

线性表是n个数据特性相同的元素的组成有限序列,是最基本且常用的一种线性结构(线性表,栈,队列,串和数组都是线性结构),同时也是其他数据结构的基础。线性表有以下特点:
由0个或多个数据元素组成的有限序列

  1. 是一个序列
  2. 第一个无前驱,最后一个无后续
  3. 元素有限

1 顺序表

用一段地址连续的存储单元依次存储线性表的数据结构。顺序存储结构封装的三个属性

  1. 起始位置
  2. 最大存储容量 MaxSize
  3. 当前长度 length
    顺序表存和读的时间复杂度为O(1),插入和删除的时间复杂度为O(n)。关于时间复杂度请参考
    https://blog.csdn.net/dulalarepost/article/details/89336730
    关于顺序表的优缺点:
    优点:
  4. 无需增加存储空间
  5. 可以快速存取表中任意元素
    缺点:
  6. 插入和删除需要移动大量元素
  7. 当线性表长度较大时,难以确定存储空间容量
  8. 容易造成空间“碎片”
    有关顺序表实现的功能,直接上代码:
#include<iostream>

using namespace std;

#define MAXSIZE 15

typedef int DateType;

//struct 后面省略了定义的变量,因为重命名为SeqList
//SeqList不是变量名,而是异种类型,相当于int,double
typedef struct {
	DateType date[MAXSIZE];//通常用数组描述顺序表的数据结构
	int SeqLength;//线性表程度
}SeqList;

SeqList *Init_SeqList();//初始化
void Define_SeqList(SeqList *L, int n);//填充顺序表内容
void Display_SeqList(SeqList *L);//提取顺序表中元素
int Insert_SeqList(SeqList *L, int i, DateType x);//添加元素到指定位置(从开始)
int Delete_SeqList(SeqList *L, int i);//删除指定位置元素(从指定位置开始)

//函数实现
SeqList *Init_SeqList() {
	SeqList *L;//相当于 int *L,但这个L可以细分,不是指针.,指针型用->
	L = new SeqList;
	L->SeqLength = 0;
	return L;
}

void Define_SeqList(SeqList *L, int n) {
	cout << "请依次输入顺序表中要存储的元素:" ;
	for (int i = 1; i <=n; i++) {
		cin >> L->date[i];
		L->SeqLength++;
	}
}

void Display_SeqList(SeqList *L) {
	cout << "顺序表中的元素为:";
	for (int i = 1; i <= L->SeqLength; i++) {

		cout << L->date[i]<<" ";
	}
	cout << endl;
}

int Insert_SeqList(SeqList *L, int i, DateType x) {
	cout << "把元素" << x << "插入到位置" << i << "上去!" << endl;
	int j;
	if (L->SeqLength == MAXSIZE - 1) {
		cout << "没有位置存放新的元素!" << endl;
		return -1;
	}
	if (i<1 || i>L->SeqLength + 1) {
		cout << "位置错误!";
		return -2;
	}
	for (j = L->SeqLength; j >= i; j--) {
		L->date[j + 1] = L->date[j];

	}
	L->date[i] = x;
	L->SeqLength++;
	cout << "插入成功!" << endl;
	Display_SeqList(L);
	return 1;
}

int Delete_SeqList(SeqList *L, int i) {
	cout << "删除位置" << i<<"上的元素" << endl;
	int j;
	if (L->SeqLength == 0) {
		cout << "没有元素可以删除!";
		return -1;
	}
	if (i < 1 || i >= L->SeqLength + 1) {
		cout << "位置错误!" << endl;
		return -2;
	}

	for (j = i; j <= L->SeqLength;j++) {
		L->date[j] = L->date[j+1];
	}
	L->SeqLength--;
	cout << "已删除,结果为:" << endl;
	Display_SeqList(L);
	return 1;
}

int main() {
	SeqList *L;
	L = Init_SeqList();
	Define_SeqList(L, 5);
	Display_SeqList(L);
	Insert_SeqList(L, 3, 25);
	Delete_SeqList(L, 3);

	system("pause");
	return 0;
}

实践结果如下:
在这里插入图片描述

2 单链表

顺序存储是将数据存储在一段连续的空间中,这样对数据的插入和删除很不利,为了节约空间,我们可以使用链式存储,方法是每个元素多用一个位置存储指向下一个位置的指针,这样可以从第一个元素找到第二个元素,第二个元素可以找到第三个元素。
在这里插入图片描述
存数据元素信息的域称为数据域,把存储直接候后继位置称为指针域,指针域中存储的信息称为指针或链。两部分加一起称为结点。链表第一个结点的存储位置叫头指针,最后一个结点的指针为空(NULL)。头结点数据域不存储信息,头指针是指链表指向第一个结点的指针。

2.1 单链表的插入

若想在ai和ai+中插入s其中结点p由ai和p->next组成,结点s由e和s->next组成,结点s由e和s->next组成。所以只需要将
s->next=p->next;
p->next=s;
单链表第i个数据插入结点的算法思路:
1、声明一节点p指向链表头结点,初始化j从1开始;
2、当j<1时,就遍历链表,让p的指针向后移动,不断指向下一节点,j累计加1;
3、若到链表末尾p为空时,说明第i个元素不存在;
4、若查找成功,系统中生成空节点s;
5、将数据元素e赋值给s->date;
6、两个标准语句;
7、返回成功。

2.2 单链表的删除

现有结点p:由a1和p->next组成 结点q:由a2和q->next组成 以及下一个元素a3

若要删除元素a2,则需要:
p->next=p->next->next;

q=p->next;
p->next=q->next;

单链表第i个数据删除结点的算法思路:
1、声明一节点p指向链表头结点,初始化j从1开始;
2、当j<1时,就遍历链表,让p的指针向后移动,不断指向下一节点,j累计加1;
3、若到链表末尾p为空时,说明第i个元素不存在;
4、若查找成功,将欲删除结点p->next赋值给q;
6、标准语句p->next=q->next;;
7、将q结点中的数据赋值给e,作为返回;
8、释放q结点。
对于插入或删除越频繁的操作,单链表优势越明显。

2.3 创建整表

单链表整表创建的算法思路:
1、声明一结点p和计数变量i;
2、初始化一空链表L;
3、让L的头结点的指针指向NULL,即建立一个带头结点的单链表;
4、循环实现后继结点的赋值和插入。
方法有头插法建立单链表以及尾插法创建单链表。
单链表基本操作代码如下:

#include<iostream>

using namespace std;

typedef int DateType;
typedef struct LNode {
	DateType data;
	struct LNode *next;
} LNode;

//用尾插法创建链表
LNode *Creat_Tail(int n) {
	LNode *head; //指向头结点的指针
	LNode *L=NULL;  //链表指针
	LNode *current; //临时指针

	head = (LNode *)malloc(sizeof(LNode));    //为头结点分配内存空间
	head->next = NULL;                      //将头结点指针域清空
	current = head;                           //先将pre指向头结点

	cout << "采用尾插法创建链表:" << endl;
	for (int i = 1; i <= n; i++) {
		L = (LNode *)malloc(sizeof(LNode));//为要插入的结点分配空间
		cout << "请输入第" << i << "个数字:";
		cin >> L->data;
		current->next = L;
		current = L;
	}
	L->next = NULL; //将最后一个结点的指针域清空
	return head;    //返回链表的首地址
}

//用头插法创建链表
LNode *Creat_Head(int n) {
	LNode *head;       //指向头结点的指针
	LNode *s=NULL;     //链表指针

	head = (LNode *)malloc(sizeof(LNode));//给头结点分配内存空间
	head->next = NULL;
	cout << endl;
	cout << "采用头插法创建链表:" << endl;
	for (int i = 1; i <= n; i++) {
		s = (LNode *)malloc(sizeof(LNode));
		cout << "请输入第" << i << "个数字:";
		cin >> s->data;
		s->next = head->next;
		head->next = s;
	}
	return head;
}



//将链表输出
void Display_List(LNode *h) {
	cout << "单链表为:" << endl;
	LNode *p;
	p = h->next;   //让p指针指向链表头结点
	while (p) {
		cout << p->data << " ";
		p = p->next;
	}
	cout << endl;
}

//将数据插入链表
LNode *Insert_List(LNode *list,int num,int Insert_num) {
	cout << "在" << num << "后插入" << Insert_num << endl;
	//head = (LNode *)malloc(sizeof(LNode));
	LNode *p;
	p = list;
	
	while (p != NULL) {
		if (p->data == num) {
			LNode *pNew = (LNode *)malloc(sizeof LNode);
			pNew->data = Insert_num;
			pNew->next =p->next;
			p->next = pNew;
			break;
		}
		p = p->next;
	}
	return list;
}

LNode *Delete_List(LNode *list, int num) {
	cout << "删除元素" << num << "后" << endl;
	if (list->data == num) {
		return list->next;
	}

	LNode *p,*pn;
	p = list;
	pn = NULL;

	while (p != NULL) {
		pn = p;
		p = p->next;
		if (p == NULL) {
			cout << "表中没有此元素!" << endl;
		}
		else if(p->data==num){
			pn->next = p->next;
		}
	}

	return list;
}

int main() {
	LNode *list1 = Creat_Tail(5);
	Display_List(list1);

	//LNode *list2 = Creat_Head(5);
	//Display_List(list2);

	LNode *list3 = Insert_List(list1, 5, 6);
	Display_List(list3);

	LNode *list4 = Delete_List(list3, 5);
	Display_List(list4);
	system("pause");
	return 0;
}

实践结果如下:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值