数据结构笔记(自用)

线性表(线性结构)

同一线性表中的元素属同一数据对象。

一个线性表可记为:

(a1,a2,……,a i-1,ai,a i+1,……,an),n>=0

n为表的长度,当n=0时,称为空表。称i为ai在线性表中的位序。a i-1是ai的直接前驱,a i+1是ai的直接后继。

ADT List{

数据对象:

数据关系:

基本操作:

}ADT List

顺序存储(随机存取)

表中逻辑上相邻的元素在存储位置上也是相邻的。“物理位置相邻”

在内存中用地址连续的一块存储空间依次存放线性表的数据元素。

用这种存储形式存储的线性表称为顺序表。

假设每个数据元素占d个存储单元,且将ai的存储地址表示为Loc(ai),则有如下关系:

Loc(ai)=Loc(a1)+i*d

Loc(ai)是线性表的第一个数据元素a1的存储地址,通常称为线性表的基地址。只要确定了线性表的基地址,线性表中任一数据元素都可随机存取。

顺序表的类型定义:

假定线性表的数据元素的类型为 ElemType (根据实际定义为int、char等等)

#define MAXSIZE 100        //顺序表的容量
   //常量MAXSIZE称为顺序表的容量,表示线性表实际可能达到的最大长度,其值通常根据具体问题的需要而定

typedef struct

{

ElemType data[MAXSIZE];   //存放顺序表的元素。数据域data是一个一维数组

int len;                  //顺序表的实际长度

}SqList;                  //顺序存储结构类型为SqList

线性表基本运算在顺序表上的实现:

注意:C语言中数组的下标从“0”开始。若L是SqList类型的顺序表,则表中第i个元素是L.data[i-1]

1.初始化线性表运算

void InitList(SqList &sq)
{
     sq.len=0;
}

2.求线性表长度运算

int ListLength(SqList sq)
{
return(sq.len);
}

3.求线性表中第i个元素运算

ElemType GetElem(SqList sq,int i)
{
if(i<1||i>sq.len)   //i值不合法
  return 0;
else
  return(sq.data[i-1];
}

4.按值查找运算

int LocateElem(SqList sq,ElemType e)
{
int i=0;
while(i<sq.len)&&(sq.data[i]!=e)  i++;   //将表中元素逐个与e比较
if(i>=sq.len)
  return 0;
else
  return i+1;
}

5.插入元素运算

时间复杂度O(n)

//在表的第i(1<=i<=n+1)个位置上,插入一个新结点e  sq.data[i-1]
//需要将第n至第i个元素向后移动一个位置。表长+1
int ListInsert(SqList &sq,int i,ElemType e)
{
int j;
if(i<1||i>sq.len+1) return 0;  //i值不合法
for(j=sq.len;j>=i;j--)         //①插入位置及之后的元素右移
   sq.data[j]=sq.data[j-1];
sq.data[i-1]=e;                //②插入e
sq.len++;                      //③表长增1
return 1; 
}

6.删除元素运算

时间复杂度O(n)

//删除表中第i(1<=i<=n+1)个位置上的元素  sq.data[i-1]
//将第i+1至第n个元素向前移动一个位置。表长-1
int ListDelete(SqList &sq,int i)
{
int j;
if(i<1||i>sq.len) return 0;  //i值不合法
for(j=i;j<sq.len;j++)        //①被删除元素之后的元素左移
   sq.data[j-1]=sa.data[j];
sq.len--;                    //②表长-1
return 1;
}

数组定义:

//数组静态分配
typedef struct{
ElemType data[MAXSIZE];
int length;
}SqList;  //顺序表类型


//数组动态分配
typedef struct{
ElemType *data;
int length
}SqList; //顺序表类型
SqList L;
L.data=(ElemType*)malloc(sizeof(ElemType)*MAXSIZE);

 C语言的内存动态分配

需要加载头文件:<stdlib.h>

malloc(m)函数:开辟m字节长度的地址空间,并返回这段空间的首地址

sizeof(x)运算:计算变量x的长度

free(p)函数:释放指针p所指变量的存储空间,即彻底删除一个变量

C++的动态存储分配:

new 类型名T  (初值列表)

int *p1=new int;  或  int *p1=new int(10);

功能:申请用于存放T类型对象的内存空间,并依初值列表赋以初值

结果值:成功:T类型的指针,指向新分配的内存。失败:0(NULL)

delete 指针p;

功能:释放指针p所指向的内存。p必须是new操作的返回值.

C++中的参数传递:

  • 函数调用时传送给形参表的实参必须与形参三个一致:类型、个数、顺序
  • 参数传递有两种方式:传值方式(参数为整型、实型、字符型等)

                                           传地址:参数为指针变量、参数为引用类型、参数为数组名

线性表的链式存储结构(链表)

用一组任意的存储单元来依次存放线性表的结点。逻辑次序和物理次序不一定相同。

单链表(非随机存取):每一个结点只有一个指针域

单链表结点结构: data next

data域是数据域,用来存放结点的值。next是指针域(也称链域),用来存放结点的直接后继的地址(或位置)。通过每个结点的指针域将线性表的n个结点按其逻辑次序连接在一起。

整个单链表的存取必须从头结点开始进行,头指针head指向第一个结点。最后一个节点无后继,指针域为空NULL。

若单链表的头指针为“空”(head=NULL),则表示线性表为“空”表,其长度为0.

为了便于一些运算的实现,在单链表的首结点之前附设一个结点,称为“头结点”。单链表的头指针指向头结点。

头结点的数据域可以不存储任何信息,也可以存储一些附加信息(如线性表的长度)。线性表非空时,头结点的指针域存储指向第一个结点的指针;线性表为空时,头结点的指针域为空。

单链表可由头指针唯一确定,在C/C++语言中,可用“结构指针”来描述。

单链表结点类型定义:

typedef struct LNode
{
ElemType data;       //数据域
struct LNode *next;  //指针域
}LNode,*LinkList;

有了上述的类型定义,可以用LNode或LinkList来声明单链表头指针的类型:

LNode *head;  //更常用
//或
LinkList head;

//定义链表:
LinkList L;

线性表基本运算在单链表上的实现

1.初始化线性表

//创建一个空的单链表
//先创建一个头结点,并将单链表的头指针指向该头结点,然后将头结点的next域置为空,data域不设任何值。
void InitList(LinkList &h)
{
h=(LNode*)malloc(sizeof(LNode));  //c++:h=new LNode;
h->next=NULL;
}

2.判断链表是否为空

int ListEmpty(LinkList L)
{
if(L->next)  return 0; //非空
else  return 1;
}

3.清空链表

//链表仍存在,但表中无元素,称为空链表(头指针和头结点仍在)


版权声明:本文为m0_59807207原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。