数据结构--线性表

一、概念

零个或多个数据元素的有限序列
的是用一段地址连续的存储单元依次存储线性表的数据元

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

存储器中的每个存储单元都有自己的编号,这个编号称为地址
每个数据元素,不管它是整型,实型还是字符型,它都是需要占用一定的存储单元空间的
线性表的存取操作时间性能为
在这里插入图片描述

假设占用的是 c 个存储单元,那么对于线性表的第 i 个数据元素 的存储位置都可以由 推导算出:

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

二、顺序表的实现 --数组代码

线性表是具有相同数据类型的n(n>0)个数据元素的有限序列,其中n为表长,当n=0时线性表是一个空表

#include "stdafx.h"
#include <iostream>
using namespace std;
#define MaxSize 30
//#define  LIST_INIT_SIZE 80//线性表存储空间的初始化分配量
//#define LISTINCREMENT 10//线性表存储空间的分配增量
typedef    int Elemtype;
 typedef  struct Sqlist *List;
 struct Sqlist
{
	Elemtype data[MaxSize];
	int length;
};
 //struct  Sqlist  L;
 //List PtrL;
 //创建空的顺序表
 List  MakeEmpty()
 {
	 List PtrL;
	 PtrL = (List)malloc(sizeof(struct Sqlist));
	 PtrL->length = -1;	
	 return  PtrL;
 }
 //创建顺序表
 void  CreateList(List Ptrl)
 {
	
	 for (int i = 0; i < 10; i++)
	 {
		 Ptrl->data[i] = i;
		 Ptrl->length++;
	 }

	 return  ;
 }
 //查找顺序表的元素的位置
 int  find(Elemtype X, List  Ptrl)
 {
	 int i = 0;
	 while (i <= Ptrl->length&&Ptrl->data[i] != X)
		 i++;
	 if (i > Ptrl->length)
		 return -1;
	 else
		 return i;
 }
 //插入元素
 void insert(Elemtype X, int i, List Ptrl)
 {
	 int j;

	 if (Ptrl->length == MaxSize - 1)
	 {
		 printf("表已满,无法插入\n");
			 return;
	 }
	 if (i == 1 || i > Ptrl->length + 2)
	 {
		 printf("插入位置不合法,插入失败\n");
		 return;
	 }
	 for (j = Ptrl->length;j>=i; j--)
	 {
		 Ptrl->data[j + 1] = Ptrl->data[j];
	 }
	 Ptrl->data[i] = X;
	 Ptrl->length++;
	 printf("插入成功\n");
	 return;
 }
 //删除元素
 void  deleteEnum( int i, List Ptrl)
 {
	 int j;
	 if (i < 0 || Ptrl->length < i)
	 {
		 printf("数组内不存在此元素位置\n");
		 return;
	 }
	 for (j = i + 1; j <= Ptrl->length; j++)
	 {
		 // 从前往后依次向前挪一个,将 a[i] 覆盖了
		 Ptrl->data[j - 1] = Ptrl->data[j];
	 }
	 Ptrl->length--;
 }
 // 按序查找第K个位置的元素
 Elemtype FindKth(int K, List L) {
	 if (K < 0 || L->length < K) {  //位置越界
		 printf("L->Data[%d]不存在元素\n", K);
		 return  -1;
	 }
	 return L->data[K];
 }
 Elemtype ListLength(List  Ptrl)
 {
	 return Ptrl->length;
 }
 void PrintList(List  Ptrl)
 {
	 for (int i = 0; i < Ptrl->length; i++)
	 {
		 printf("元素:%d\n", Ptrl->data[i]);
	 }
 }
 //主函数
int main()
{
	List PtrL= MakeEmpty();
	CreateList(PtrL);
	PrintList(PtrL);
	insert(9, 9, PtrL);
	PrintList(PtrL);

	FindKth(5, PtrL);
	find(3, PtrL);
	deleteEnum(5, PtrL);
	PrintList(PtrL);
    return 0;
}

三、单链表的–链式存储代码

// 线性表-单链表.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
typedef int ElemType;
typedef struct Lnode *List;
//List MakeEmpty(); //初始化链表 
//int Length(List L);  // 以遍历链表的方法求链表长度 
//List FindKth(int K, List L);  // 按序号查找 
//List Find(ElementType X, List L);  // 按值查找 
//List Insert(ElementType X, int i, List L);  //将 X 插入到第 i-1(i>0) 个结点之后 
//List Delete(int i, List L); // 删除第 i(i>0) 个结点 
//void Print(List L); // 输出链表元素 
struct Lnode
{
	ElemType data;
	List   Next;
};
List L;
//创建一个空链表
List MakeEmpty()
{
	List  L = (List)malloc(sizeof(struct Lnode));
	L = NULL;
	return L;
}
//求链表的长度
ElemType  Length(List l)
{
	ElemType len = 0;
	List p = l;
	while (p!=NULL)
	{
		p = p->Next;
		len++;
	}
	return len;
}
//基于位置找元素
List FindKth(int K, List L) 
{
	List p = L;
	int i = 1;
	if (p == NULL)
		return  NULL;
	while (p&&i<K)
	{
		p = p->Next;
		i++;
	}
	if (i == K)
		return p;
	else
		return NULL;
}
//按值查找
List  Find(ElemType X, List L)
{
	List P = L;
	while (P&&P->data!=X)
	{
		P = P->Next;
	}
	// 找到了,返回 p
	// 未找到,返回 NULL,此时 p 等于 NULL 
		return P;
}
//插入
//1. 用 s 指向一个新的结点
//2. 用 p 指向链表的第 i - 1 个结点
//3. s->Next = p->Next,将 s 的下一个结点指向 p 的下一个结点
//4. p->Next = s,将 p 的下一结点改为 s   * /
List Insert(ElemType X, int i, List L)
{

	List P,S;
	if (i==1)
	{
		S=(List)malloc(sizeof(struct Lnode));
		S->data = X;
		S->Next = L;
		return  S;

	}
	P = FindKth(i - 1,L);
	if (!P)
	{
		printf("结点错误");
		return NULL;
	}
	else
	{
		S = (List)malloc(sizeof(struct Lnode));
		S->data = X;
		S->Next = P->Next;
		P->Next = S;
		return L;
	}


}

/* 删除
1. 用 p 指向链表的第 i-1 个结点
2. 用 s 指向要被删除的的第 i 个结点
3. p->Next = s->Next,p 指针指向 s 后面
4. free(s),释放空间
*/
List Delete(int i, List  L)
{
	List P, S;
	if (i<1) return NULL;
	if (i==1)
	{
		S = L;
		if (L)
		{
			L = L->Next;
			

		}
		else
		{
			L = NULL;
		}
		free(S);
		return L;
	}
	P = FindKth(i - 1, L);    // 查找第 i-1 个结点
	if (!P || !(P->Next)) {     // 第 i-1 个或第 i 个结点不存在 
		printf("结点错误");
		return NULL;
	}
	else {
		S = P->Next;    // s 指向第 i 个结点 
		P->Next = S->Next;  //从链表删除 
		free(S);  // 释放被删除结点 
		return L;
	}

}
// 输出链表元素 
void Print(List L) {
	List t;
	int flag = 1;
	printf("当前链表为:");
	for (t = L; t; t = t->Next) {
		printf("%d  ", t->data);
		flag = 0;
	}
	if (flag)
		printf("NULL");
	printf("\n");
}
int main()
{
	L = MakeEmpty();
	Print(L);
	L = Insert(11, 1, L);
	L = Insert(25, 1, L);
	L = Insert(33, 2, L);
	L = Insert(77, 3, L);
	Print(L);
	printf("当前链表长度为:%d\n", Length(L));
	printf("此时链表中第二个结点的值是:%d\n", FindKth(2, L)->data);
	printf("查找22是否在该链表中:");
	if (Find(22, L))
		printf("是!\n");
	else
		printf("否!\n");
	printf("查找33是否在该链表中:");
	if (Find(33, L))
		printf("是!\n");
	else
		printf("否!\n");
	L = Delete(1, L);
	L = Delete(3, L);
	printf("----------删除后-----\n");
	Print(L);
    return 0;
}

四、双向链表–代码

在这里插入图片描述

// 线性表-双向链表.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
typedef int ElemType;
typedef struct DNode *DLinklist;
 struct DNode {            //定义双链表结点类型
	ElemType data;               //数据域
	struct DNode *prior, *next;  //前驱和后继指针
};

//初始化双链表
bool InitDLinkList(DLinklist &L) {
	L = (DNode *)malloc(sizeof(DNode));      //分配一个头结点
	if (L == NULL)                              //内存不足,分配失败
		return false;

	L->prior = NULL;   //头结点的prior指针永远指向NULL
	L->next = NULL;    //头结点之后暂时还没有结点
	return true;
}

void testDLinkList(DLinklist L) {
	//初始化双链表
	         // 定义指向头结点的指针L
	InitDLinkList(L);    //申请一片空间用于存放头结点,指针L指向这个头结点
						 //...
}
//find
DNode* FindDP(int position,DLinklist &L) {
	
	DNode* P = L;
	int index = 0;
	while (P&&index < position)
	{
		P = P->next;
		index++;
	}
	return  P;
}

//判断双链表是否为空
bool Empty(DLinklist L) {
	if (L->next == NULL)    //判断头结点的next指针是否为空
		return true;
	else
		return false;
}
bool InsertNextDNode(DNode *p, DNode *s) { //将结点 *s 插入到结点 *p之后
	if (p == NULL || s == NULL) //非法参数
		return false;

	s->next = p->next;
	if (p->next != NULL)   //p不是最后一个结点=p有后继结点  
		p->next->prior = s;
	s->prior = p;
	p->next = s;

	return true;
}
//删除p结点的后继结点
bool DeletNextDNode(DNode *p) {
	if (p == NULL) return false;
	DNode *q = p->next;            //找到p的后继结点q
	if (q == NULL) return false;     //p没有后继结点;
	p->next = q->next;
	if (q->next != NULL)           //q结点不是最后一个结点
		q->next->prior = p;
	free(q);

	return true;
}

//销毁一个双链表
bool DestoryList(DLinklist &L) {
	//循环释放各个数据结点
	while (L->next != NULL) {
		DeletNextDNode(L);  //删除头结点的后继结点
		free(L); //释放头结点
		L = NULL;  //头指针指向NULL

	}
	return true;
}
void PrintPrior(DNode *T)
{
	DNode *p = T;
	while (p != NULL) {
		//对结点p做相应处理,eg打印
		if (p != NULL)
		printf("%d \n ", p->data);
		p = p->prior;
		
	}
}
void PrintNext(DNode *T)
{
	DNode *p = T;
	while (p != NULL) {
		//对结点p做相应处理,eg打印
		
		p = p->next;
		if (p != NULL)
			printf("%d \n ", p->data);
	}
}



int main()
{
	DLinklist L=NULL;
	DNode *node = NULL, *node1 = NULL, *node2 = NULL, *node3 = NULL;
	InitDLinkList(node);
	InitDLinkList(node1);
	InitDLinkList(node2);
	InitDLinkList(node3);
	InitDLinkList(L);
	//testDLinkList(L);
	node->data = 1;
	InsertNextDNode(L, node);
	node1->data = 2;
	InsertNextDNode(L, node1);
	node2->data =3;
	InsertNextDNode(L, node2);
	DNode* T=	FindDP(1, L);
	DeletNextDNode(T);

	PrintNext(L);
	PrintPrior(L);
    return 0;
}


六、循环链表-代码

单链表和循环单链表的比较:
**单链表:**从一个结点出发只能找到该结点后续的各个结点;对链表的操作大多都在头部或者尾部;设立头指针,从头结点找到尾部的时间复杂度=O(n),即对表尾进行操作需要O(n)的时间复杂度;
**循环单链表:**从一个结点出发,可以找到其他任何一个结点;设立尾指针,从尾部找到头部的时间复杂度为O(1),即对表头和表尾进行操作都只需要O(1)的时间复杂度;

==优点:==从表中任一节点出发均可找到表中其他结点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值