线性表
(linear list)简称表,是n(n≥0)个具有相同类型的数据元素的有限序列。
顺序表
——线性表的顺序存储结构
- 只要确定了存储顺序表的起始地址,计算任意一个元素的存储地址的时间是相等的,具有这种特点的存储结构称为随机存储结构。
- 存储结构定义
const int MaxSize = 10;
typedef int DataType;
typedef struct
{
DataType data[MaxSize];
int length;
} SeqList;
- 简单实现
// 初始化
void InitList(SeqList &L)
{
L.length = 0;
}
// 创建,根据数组a创建长度为n的顺序表
void CreateList(SeqList &L, DataType a[], int n)
{
int i;
if(n > MaxSize) {
printf("参数非法!");
exit(-1);
}
for(i = 0; i < n; i++)
{
L.data[i] = a[i];
}
L.lenght = n;
}
// 按位、值查找
DataType GetData(SeqList &L, int i)
{
if(i<1 || i>L.length) {
printf("查找位置非法")
exit(-1);
}
return L.length[i]
}
int LocateData(SeqList &L, DataType d)
{
int i;
for(i = 0; i < L.length; i++)
{
if (L.data[i] == d)
return i+1; // 返回位置(第几个)
}
return 0; // 没有找到
}
// 插入
void Insert(SeqList &L, int i, DataType d)
{
if(L.length >= MaxSize) {
printf("上溢");
exit(-1);
}
if(i < 1 || i > L.length) {
print("位置错误");
exit(-1);
}
int j;
for(j = L.length; j>= i; j--)
L.data[j] = L.data[j-1];
L.data[i-1] = d;
L.length++;
}
// 删除第i个元素
DataType Delete(SeqList &L, int i)
{
if (L.length == 0) {
printf("下溢");
exit(-1);
}
if (i < 1 || i > L.length) {
printf("删除位置错误");
exit(-1);
}
int j;
DataType d = L.data[i-1];
for(j = i; j < L.length; j++)
L.data[j-1] = L.data[j];
L.length--;
return d;
}
单链表
- 简单定义:使用一组任意的存储单元存放线性表的元素,存储单元即可以是连续的也可以是不连续的,可以分散在内存的任意位置。
- 存储结构
typedef int DataType;
typedef struct Node
{
DataType data;
Node *next;
} Node, *first;
- 简单实现
// 初始化
Node* InitList(Node * first)
{
first = (Node *)malloc( sizeof( Node ) );
first->next = NULL;
return first;
}
// 遍历
void PrintList(Node *first)
{
p = first->next;
whilh (p != NULL) {
print(p->data);
p = p->next;
}
}
// 按位、值查找
DataType GetData(Node *first, int i)
{
p = first->next;
int count = 1;
while(p != NULL && count < i) {
p = p->next;
count++;
}
if(p == NULL) {
printf("查找失败");
exit(-1);
} else {
return p->next;
}
}
int Locate(Node *first, DataType d)
{
p = first->next;
int count = 1;
while(p != NULL) {
if(p->data == d)
return count;
p = p->next;
count++;
}
return 0;
}
// 插入
void Insert(Node *first, int i, DataType d)
{
p = first;
int count = 0;
while(p != NULL && count < i-1) {
p = p->next;
count++;
}
if(p == NULL) {
printf("插入失败");
exit(-1);
} else {
Node *s;
s = (Node *)malloc( sizeof(Node) );
s->data = d;
s->next = p->next;
p->next = s;
}
}
// 删除
DataType Delete(Node *first, int i)
{
p = first;
int count = 0;
while(p != NULL && count < i-1) {
p = p->next;
count++;
}
if(p == NULL || p->next == NULL) {
printf("删除失败");
exit(-1);
} else {
Node *q;
DataType d;
q = (Node *)malloc( sizeof(Node) );
q = p->next;
d = p->data;
p->Next = q->next;
free(q);
return d;
}
}
// 头插法建立单链表
Node* Create(Node *first, DataType a[], int n)
{
first = (Node *)malloc( sizeof(Node) );
first->next = NULL;
int i;
for(i = 0; i < n; i++)
{
Node *s;
s = (Node *)malloc( sizeof(Node) );
s->data = a[i];
s->next = first->next;
first->next = s;
}
return first;
}
// 尾插法建立单链表
Node* Create(Node *first, DataType a[], int n)
{
first = (Node *)malloc( sizeof(Node) );
Node *r;
r = first;
int i;
for(i = 0; i < n; i++)
{
Node *s;
s = (Node *)malloc( sizeof(Node) );
s->data = a[i];
r->next = s;
r = s;
}
r->next = NULL;
return first;
}
双链表
- 在单链表的基础上设置一个前驱节点
- 存储结构定义
typedef int DataType;
typedef struct DulNode
{
DataType data;
DulNode *prior, *next
} DulNode, *first;
- 简单实现
// 插入
void Insert(DulNode *first, int i, DataType d)
{
Node *p;
p = first;
int count = 0;
while(p != NULL && count < i-1) {
p = p->next;
count++;
}
if(p == NULL) {
printf("插入失败");
exit(-1);
} else {
Node *s;
s = (Node *)malloc( sizeof(Node) );
s->data = d;
s->prior = p;
s->next = p->next;
p->next->prior = s;
p->next = s;
}
}
// 删除
DataType Delete(Node *first, int i)
{
Node *p;
p = first;
int count = 0;
while(p != NULL && count < i) {
p = p->next;
count++;
}
if(p == NULL) {
printf("删除失败");
exit(-1);
} else {
Node *q;
DataType d;
q = p->next;
d = q->data;
(p->prior)->next = p->next;
(p->next)->prior = p->prior;
free(q);
return d;
}
}
循环链表
- 循环单链表
- 循环双链表
静态链表
- 用数组来表示单链表,用数组下标来模拟单链表的指针
- 存储结构定义
const int MaxSize = 10;
typedef int DataType;
typedef struct
{
DataType data;
int next;
} SNode, SList[MaxSize];
- 简单实现
// 插入
s = avail;
avail = SList[avail].next;
Slist[s].data = d;
SList[s].next = SList[p].next;
SList[p].next = s
// 删除
q = SList[p].next;
Slist[p].next = SList[q].next;
SList[q].next = avail;
avail = q;
约瑟夫环问题
- 问题描述
约瑟夫环问题由古罗马史学家约瑟夫提出,他参加并记录了公元66-70年犹太人反抗罗马帝国的起义。在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。 - C++实现
#include<iostream>
#include<list>
#include<cstdlib>
int main()
{
int total=0;
int key=0;
cout<<"input total:";
cin>>total;
cout<<"input key:";
cin>>key;
if(key>total || key <1||total <1)
{
cout<<"error input!"<<endl;
}
list<int>* table = new list<int>();
for(int i =1;i<=total;++i)
table->push_back(i);
int shout = 1;
for(list<int>::iterator it=table->begin();table->size()!=1;)
{
if(shout++==key) {
it = table->erase(it);
shout=1;
} else {
++it;
}
if(it==table->end()) {
it=table->begin();
}
}
cout<<"the last one:";
cout<<*table->begin()<<endl;
return 0;
}