数组是由下标 (index) 和值(value)组成的有序对(index,value)的集合。
也可以定义为是由相同类型的数据元素组成有限序列
数组在内存中是采用一组连续的地址空间存储的,正是由于这种原因,才可以实现下标运算。所有数组都是一个一维向量。
数组在内存中主要采用两种存储方式:
(1)以行序为主的存储方式;
(2)以列序为主的存储方式。
不同的存储方式有不同元素地址计算方法。
下(上)三角矩阵对角线以上(下)元素都为零,根据这个特点可以定义一个长度为n*(n+1)/2的一维数组sa来存储。
下标从1开始计数
根据稀疏矩阵大部分元素的值都为零的特点,可以只存储稀疏矩阵的非零元素,三元组分别记录非零元素的行,列位置和元素值。
#include<stdio.h>
#include<stdlib.h>
#define OVERFLOW -1
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSize 12500
typedef int ElemType;
typedef int Status;
typedef struct {
int i,j; //非零元的行下标和列下标
ElemType e; //非零元的值
}Triple;//三元组的类型
typedef struct {
Triple data[MAXSize + 1];//data[0]未用
int mu, nu, tu;
}TSMatrix;//稀疏矩阵类型
Status TransposeSMatrix(TSMatrix m, TSMatrix* t)
{
int p, q, col;
t->mu = m.mu;
t->nu = m.nu;
t->tu = m.tu;
if (t->tu)
{
q = 1;
for(col=1;col<=m.nu;++col)
for (p = 1; p < m.tu; ++p)
if(m.data[p].j==col){
t->data[q].i = m.data[p].j;
t->data[q].j = m.data[p].i;
t->data[q].e = m.data[p].e;
++q;
}
}
return OK;
}
广义表的元素可以是子表,子表的元素还可以是子表,存储空间难以确定,常采用链式存储。
#include<stdio.h>
#include<stdlib.h>
#define OVERFLOW -1
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int AtomType;
//广义表的头尾链表存储表示
typedef enum {ATOM,LIST}ElemTag;//ATOM域存放该原子的值
typedef struct GLNode {
ElemTag tag;
union {
AtomType atom; //tag=0时,是原子节点,atom里存放该原子的值
struct //tag=1时,是表节点
{//hp指向子表头,tp指向广义表的下一个
struct GLNode * hp, * tp;
}ptr;
};
}*GList;
例3:假定用一个循环单链表表示队列,该队列只设一个队尾指针rear,不设头指针,不设头结点:
写出:
(1)入队算法(入队元素为x);
(2)出队算法。
注意尾结点和尾指针的区别,尾指针位于第后一个节点上,尾指针的next是队头,尾结点的next是队尾
void EnQueue(ElemType x, DuLinkList rear)
{
DuLinkList p;
p = (DuLNode*)malloc(sizeof(DuLNode));//生成新结点
p->data = x;
if (rear== NULL)
{
rear = p;
rear->next = rear;
}
else
{
p->next = rear->next;
rear->next = p;
rear = p;
}
}
void DeQueue(DuLinkList rear)
{
DuLinkList p;
if (rear== NULL)
{
printf("队列空");
}
else
{
p = rear->next; //队尾
if (rear == rear->next)
{
rear = NULL;
}
else
{
rear->next = p->next;
printf("%d\n", p->data);
free(p);
}
}
}