文章主要是对于
数据结构与算法课程学习的读书记录
。欢迎学习交流。
[内容范围]第二章线性表-顺序表和链式表概念及其代码实现。
线性表: n个同类型数据元素的有限序列,记为:
L= (a1,a2,…,ai,…,an)
L为表名;
i为数据元素ai 在线性表中的位序;
n为线性表的表长; n=0 时称为空表;
数据元素之间的关系是:
ai-1领先于ai,ai领先于ai+1。
称ai-1是ai的直接前驱,ai+1是ai的直接后继,
除第一元素a1外,均有唯一的前驱;
算法设计:
思想:从LB中逐一取出元素,判断元素是否存在LA中,若不在则将这个元素插入到LA中
//依次从LB中取出第i个数据元素:List_Retrieve(Lb, i, &elem) →elem
//判elem是否在LA中存在:List_Locate(La,elem,&j)
//若不存在,则将elem插入到LA中:List_Insert(La,1,elem)
Status List_Union (SqListPtr La, SqListPtr Lb){
ElemType elem; /* 存放从Lb中取出的元素*/
Status status; /*状态代码*/
int i, j, len = List_Size(Lb); /*len存放Lb的元素个数*/
for (i=1; i<=len; i++){
List_Retrieve(Lb, i, &elem); /*取出Lb中第i个数据元素*/
status = List_Locate(La,elem,&j); /*判它是否在La中*/
if(status!= success){
/*如果不在*/
status = List_Insert(La,1,elem); /*插入到第一个位置*/
if(status!= success) break; /*插入失败则退出*/ }
else List_Add(La,j,1);/*La的第j个数据加1*/
}
return status;
}
问题:已知线性表La和Lb中的元素按照递增顺序排列,现要求将他们合并成一个新的线性表Lc,病似的Lc中元素也按照递增的顺序排列
思想:线性表Lc初始为空。依次扫描La和Lb中的元素,比较
当前元素的值,将较小值的元素插入Lc的表尾之后,如此反
复,直到一个线性表扫描完毕,然后将未完的那个线性表中
余下的元素逐个插入到Lc的表尾之后
Status List_Merge (SqListPtr La, SqListPtr Lb, SqListPtr Lc){
ElemType elem1, elem2; status = List_Init(Lc);
int i=1, j=1, k=1; /*i, j, k分别用于指示La, Lb, Lc中当前元素*/
int n = List_Size(La),m = List_Size(Lb);
while(i<=n && j<=m){
/*两个表都还未处理完*/
List_Retrieve(La,i,&elem1); List_Retrieve(Lb,j,&elem2);
if(elem1<elem2){
status = List_Insert(Lc,k,elem1); i=i+1; }
else{
status = List_Insert(Lc,k,elem2); j=j+1; }
k=k+1;
}
Status List_Merge (SqListPtr La, SqListPtr Lb, SqListPtr Lc){
…….
while(i<=n){
/*表La都还未处理完*/
List_Retrieve(La, i, &elem1);
status = List_Insert(Lc, k, elem1);
i=i+1; k=k+1; }
while(j<=m){
/*表Lb都还未处理完*/
List_Retrieve(Lb, j, &elem2);
status = List_Insert(Lc, k, elem2);
j=j+1; k=k+1; }
return status;
}
#define LIST_INIT_SIZE 100 //空间个数
#define LIST_INCREAMENT 10 //每次增加的空间个数
typedef int ElemType;//重新命名类型
typedef struct SqList//重新命名结构体
{
ElemType *elem;//一大片连续空间的首地址
int length; //长度 开始未知
int list_size;//个数 开始未知
}SqList, *Ptr;
typedef Ptr *SqlListPtr;
Status List_Init(SqListPtr L)
{
Status s = success;
L->list_size = LIST_INIT_SIZE;//宏定义的值
L->length = 0;//初始为0
L->elem = (ElemType *)malloc(sizeof(ElemType)*L->list_size);//开辟空间
if (L->elem == NULL)
s=fatal;
return s;
}
Status List_Retrival(SqListPtr L, int pos, ElemType *elem)
{
Status s = range_error;
if (L)//如果链表存在
{
if ((pos-1) >= 0 && (pos-1) < L->length)//从0开始 在范围内
{
*elem = L->elem[pos-1];//* 表示取值 取出放入
s = success;//修改状态
}
}
else
s = fatal;
return s;
}
Status List_Locate(SqListPtr L, ElemType elem, int *pos)
{
Status s = range_error;
if (L){
for (int i = 0; i < L->length; ++i){
if (L->elem[i] == elem){
*pos = i+1;
s = success;
break;
}
}
}
else s = fatal;
retu
Status List_Insert(SqListPtr L, int pos, ElemType elem)
{
Status s = range_error;
if ((pos-1) >= 0 && (pos-1) <= L->length)//在顺序表范围内
{
//顺序表存在并且还存在未使用的空间方便后移
if (L && L->length <L-> list_size )
{
//循环遍历后移 记得-1
for (int i = L->length-1; i >= pos-1; --i){
L->elem[i+1] = L->elem[i];
}
//插入
L->elem[pos-1 ] = elem;
//实际长度增加1
L->length++;
s = success;
}
}
else s = fail;
return
Status List_delete(SqListPtr L, int pos)
{
Status s = range_error;
if ((pos-1) >= 0 && (pos-1) < L->length){
if(L && L->length > 0){
for (int i = pos ; i < L->length; ++i){
L->elem[i-1] = L->elem[i ];
L->length--;
s=success;
}
}
}
else s = fail;
return s;
}
typedef struct Node
{
ElemType elem;
struct Node *next;
}Node,*Ptr;
typedef Ptr *SqListPtr;
Node n1, n2;
/* 定义2个结点变量*/
Ptr p = &n1;
/* 定义一个指向结点的指针变量p, 并存放n1的地址
(指针) */
n1.next=&n2; /* 结点n1的指针域存放结点n2的地址
*/
SqListPtr L=p; //定义一个单链表L
N2.next=NULL;
Status List_Retrieve(SqListPtr L, int pos, ElemType *elem)
{
//SqListPtr L是一个二重指针
Status s = range_error;
Ptr p = (*L)->next;; /* 带头结点,移动p指向第一个元素结点*/
int i = 1;/*计数器*/
while (p && i < pos)){
/* p指向的结点存在,且未到达指定位置*//*条件1防止pos>表长;条件2
控制取第pos个, 防pos<1 */
{
i++;
p = p->next;
}
if (p && i == pos)) /*找到指定位置,且该结点存在 防止i=0 -1 这种情况*/
{
*elem = p->data;
s = success;
}
return s;
}
Status List_Locate(SqListPtr L, ElemType elem, int *pos)
{
Status s = range_error;
Ptr p = (*L)->next;
int i = 1;
while (p != NULL){
if (p->elem == elem)break;
i++;
p = p->next;
}
if (p){
*pos = i;
s = success;
}
return s;
}
Status List_Insert(SqListPtr L, int pos-1, ElemType elem)
{
Status status ;
Ptr p,s;
status = List_Retrival (L, pos-1, &p);//判断是否存在这个位置 有没有越界
if (status == success){
s = (LinkedPtr)malloc(sizeof(Node));//创建新节点
if (s){
s->elem = 数据;//新结点挂上数据
s->next = p->next;//新节点next挂上ai
p->next = s;//ai-1挂上next
status = success;
}
else status = fatal;
}
else status = range_error;
return status;
}
//不完整 要先用查找 找到对应位置(s p)的指针
//再用如下函数进行删除
Status List_delete(SqListPtr L, int pos)
{
Status status=fail;
Ptr s, p;
status = List_Retrival (L, pos - 1, &p);
if (status == success)
{
s = p->next;
p->next = s->next;
free(s);
s = NULL;
status = success;
}
return status;
}
首先明确插入都是前插,操作都在空节点和第一个节点之间。如果要求a1 到 a n 顺序插入,那么实际上我们操作顺序是an 到 a1,看下图理解
Status List_Create(SqListPtr L, ElemType data[], int len){
Status s;
Ptr p;
s = List_Init(L);
if (s == success){
for (int i = len-1; i>=0; --i)//len个数据
{
p = (Ptr)malloc(sizeof(Node));//循环初始化len个节点
if (p)
{
p->elem = data[i];//数据放入新结点
//先填充新节点的next ,否则数据覆盖就不存在,顺序不能换
p->next = (*L)->next;
(*L)->next = p;//新结点挂载空节点的next上
}
else{
s = fail;
break;
}
}
}
return s
对于数据结构与算法课程的重新学习整理,如有错误欢迎指出。