目录
前言
大体介绍一下数据结构的知识点,便于个人复习记忆
一、线性表的定义是什么?
线性表示n个数据元素的有限序列;
在复杂的线性表(即每个数据元素都含有若干数据项)中,数据元素被称为记录,含有大量记录的此线性表则被又称为文件。
二、线性表的特点是什么?
除第一个元素外,其余元素都只有一个前驱节点;
除最后一个外,其余元素都仅有一个后继节点。
反隐了节点间一对一的关系
三、线性表的基本操作有哪些?
6.添加InsertList(List &L, int i, Data e)
7.删除DeleteList(List &L, int i, Data &e)
按位查找GetElem(List L, int i, Data &e)
按值查找LocateElem(List L, Data e,compare())
四、线性表的分类(按照存储结构分)
1.顺序表
定义:
线性表的顺序实现,即逻辑上相邻的元素在计算机物理存储单元上也是相邻的特点:
存储密度小,需要占据一块连续的存储空间
便于随机访问,查找效率快
不便于添加、删除操作
实现和初始化:
(1)静态分配
#define List_Size 100
struct Data{
int a;
double b;
};
typedef struct LNode{
Data s[List_Size]; //静态分配是以固定长度的数组来存储数据元素
int length;
}List;
bool InitList(List &L){
L.length = 0;
return true;
}
2)动态分配
#define List_Size 100
struct Data{
int a;
double b;
};
typedef struct LNode{
Data *s; //静态分配是以固定长度的数组来存储数据元素
int length;
int ListSize;
}List, *LinkList;
bool InitList(List &L){
L.s = (LinkList )malloc(List_Size*sizeof(Data));
if(L.s) return false;
L.length = 0;
L.ListSize = List_Sizel
return true;
}
由于动态分配易于扩展存储内存,因此常用动态分配来实现顺序表。
插入:
bool InsertList(List &L, int i, Data e){
if( i < 1 || i > length + 1) return false;
Data *p = &L.s[i-1];
Data *q = &L.s[L.length];
for (; q > p; q--) //必须从后面超前面右移
*q = *(q-1);
*p = e;
L.length++;
return true;
}
删除:
bool DeleteList(List &L, int i, Data &e){
if ( i < 1 || i > L.length) return false;
Data *p = &L.s[i-1];
Data *q = &L.s[length-1];
e = *p;
for(; p < q; p++)
*p = *(p+1);
L.length--;
return true;
}
查找:
//按位查找
bool GetElem(List L, int i, Data &e){
if ( i < 1 || i > length) return false;
e = L.s[i-1];
return true;
}
//按值查找
bool compare(Data x, Data y){
if(x.a == y.a)
return true;
else
return false;
}
bool LocateElem(List L,int &n, Data e){
for(int j = 0; j < L.length; j++)
if(compare(L.s[j-1],e)){
n = j+1;
return true;
}
return false;
}
2.链表
(1)单链表
初始化建立单链表:
struct Data{
int a;
double b;
};
typedef struct LNode{
Data x;
struct LNode *next;
}List,*LinkList;
//逆序插入多个数据,建立带头结点的单链表
bool InitList(LinkList &L,int n){
L = (LNode *)malloc(sizeof(LNode));
if(L) return false;
L->next = NULL;
for(; n > 0; n-- ){
LinkList p = (LinkList )malloc(sizeof(LNode));
if(p) return false;
//输入节点数据
scanf("%d,%f",p->x.a, p->x.b);
p->next = L->next;
L->next = p;
}
return true;
}
//逆序插入多个数据,建立不带头结点的单链表
bool InitList(LinkList &L, int n){
L = NULL;
for(; n > 0; n--){
LinkList p = (LinkList )malloc(sizeof(LNode));
if(p) return false;
//输入节点数据
scanf("%d,%f",p->x.a, p->x.b);
p->next = L;
L = p;
}
return true;
}
插入节点:
//按位插入节点
bool InsertList(LinkList &L, int i, Data e){
if (i < 1)
return false;
LinkList p = L;
int j = 0;
while(p && j < i-1){
p = p->next;
j++;
}
LinkList s = (LinkList )malloc(sizeof(LNode));
if(s) return false;
s.x = e;
s->next = p->next;
p->next = s;
return true;
}
//指定节点前插法(节点实际还是后插,只是将数据调换)
bool PriorElem(LinkList &p, Data e){
LinkList q = (LinkList )malloc(sizeof(LNode));
if(q) return false;
q->next = p->next;
p->next = q;
q.x = p.x;
p.x = e;
return true;
}
//指定节点后插法
bool NextElem(LinkList &p, Data e){
LinkList q = (LinkList )malloc(sizeof(LNode));
if(q) return false;
q->next = p->next;
p->next = q;
q.x = e;
return true;
}
删除节点:
bool InsertList(LinkList &L, int i, Data &e){
if( i < 1 ) return false;
LinkList p = L;
int j = 0;
while( p && j < i-1 ){
p = p->next;
j++;
}
p->next = p->next->next;
return true;
}
(2)双链表
struct Data{
int a;
double b;
};
typedef struct LNode{
Data x;
struct LNode *prior,*next;
}List,*LinkList;
//
(3)循环链表
(4)静态链表
静态链表的每个节点都是存储游标,而非下一个节点的指针。
#define List_Size 100
struct Data{
int a;
double b;
};
typedef struct LNode{
Data x;
int next; //节点的游标
}List[List_Size];
bool InitList(List &p, int n){
p[0].next = 0;
int tail = 0; //最尾部节点的位置
for(int i = 1; i <= n; i++){
Data m;
int k;
scanf("节点数据输入:%d %f", m.a, m.b);
}
总结
仅是对线性表结构实现汇总,具体分析后续记录