【数据结构】线性表总结(顺序表 单链表 双链表 循环链表)

文章目录

    • 一、线性表的顺序存储
      • 顺序存储结构的定义
      • 1、线性表的查找
      • 2、线性表的插入
      • 3、线性表的删除
      • 4、顺序表的合并
    • 二、线性表的链式存储
      • 单链表存储结构声明
      • 1、链表的初始化
      • 2、头插法建表
      • 3、尾插法建表
      • 4、按序号查找元素
      • 5、按值查找元素
      • 6、插入值
      • 7、删除结点
      • 8、单链表长度
      • 9、合并两个有序非递减链表
      • 循环链表
      • 双向链表的声明

一、线性表的顺序存储

顺序存储结构的定义

#define MAXSIZE 1001
typedef struct {
    ElemType elem[MAXSIZE];
    int last;//last是下标(始于0)
}SeqList;

1、线性表的查找

//线性表的查找(位置)
int Locate(SeqList L, ElemType e){
    //i和L.last都是下标
    i=0;
    while((i<=L.last)&&(L.elem[i]!=e)) i++;
    if(i<=L.last) return i;
    else return -1;
}

2、线性表的插入

//线性表的插入
int InsList(SeqList* L, int i, ElemType e){
    int k;
    //i是指位置(始于1) L->last是指下标(始于0)
    if((i<1) || (i>L->last+2)){
        printf("Wrong position!");
        return (ERROR);
    }
    if(L->last>=MAXSIZE-1){
        printf("The sqlist is full");
        return (ERROR);
    }
    //后面的全部往后移动一位
    for(k=L->last; k>=i-1; k--){
        L->elem[k+1]=L->elem[k];
    }
    L->[i-1]=e;//插入
    L->last++;//表长+1
    return 0;
}

3、线性表的删除

//线性表的取值删除
int DelList(SeqList* L, int i, ElemType* e){
    int k;
    //i是指位置(始于1) L->last是指下标(始于0)
    if((i<1) || (i>L->last+1)){
        printf("Wrong position!");
        return (ERROR);
    }
    *e=L->elem[i-1];
    //后面的全部往前移动一位
    for(k=L->last; k>=i-1; k--){
        L->elem[k-1]=L->elem[k];
    }
    L->last--;//表长+1
    return 0;
}

4、顺序表的合并

//非递减有序顺序表合并
void merge(SeqList* LA, SeqList* LB, SeqList* LC){
    int i=0, j=0, k=0;
    //LA和LB都没有用完,取小的放进LC
    while(i<=LA->last && j<=LB->last){
        if(LA->elem[i]<=Lb->elem[j]){
            LC->elem[k]=LA->elem[i];
            k++; i++;
        }else{
            C->elem[k]=LB->elem[j];
            k++; j++;
        }
    }
    //LA没用完
    while(i<=LA->last){
        LC->elem[k]=LA->elem[i];
        k++; i++;
    }
    //LB没用完
    while(j<=LB->last){
        LC->elem[k]=LB->elem[j];
        k++; j++;
    }    
    //LC尾下标
    LC->last=LA->last+LB->last+1;//小心下标和长度的关系
}

二、线性表的链式存储

单链表存储结构声明

typedef struct Node{
    ElemType data;
    struct Node* next;
}Node, *LinkList;

其中,同时定义了结构标记和结构类型:struct Node, typedef strcut Node, *LinkList
同时定义了两种等价的结构类型:Node 便于声明结点,Linklist 便于声明链表头指针, Linklist 结构指针类型, Linklist L 指针

1、链表的初始化

void init_linklist(LinkList *l){
    //l是指向链表头指针的指针
    *l=(LinkList)malloc(sizeof(Node));//头节点分配空间
    (*l)->next=NULL;
}
//调用
Linklist L;
init_linklist(&L)

2、头插法建表

【数据结构】线性表总结(顺序表 单链表 双链表 循环链表)_第1张图片

//头插法建表
void CreateFromHead(LinkList L){
    Node *s; char c; int flag=1;
    while(flag){
        c=getchar();
        if(c!='$'){
            s=(Node*)malloc(sizeof(Node));
            //头插法
            s->data=c;
            s->next=L->next;//新结点指向后面结点
            L->next=s;//前面结点指向新结点
        }else{
            flag=0;
        }
    }
}

3、尾插法建表

【数据结构】线性表总结(顺序表 单链表 双链表 循环链表)_第2张图片

//尾插法建表
void CreateFromTail(LinkList L){
    Node *s,*r; char c; int flag=1;
    r=L; //r用于跟踪为节点
    while(flag){
        c=getchar();
        if(c!='$'){
            s=(Node*)malloc(sizeof(Node));
            //尾插法
            s->data=c;
            r->next=s;//尾部指向新结点
            r=s;//继续跟着尾部
        }else{
            flag=0;
            r->next=NULL;
        }
    }
}

4、按序号查找元素

//按序号查找
Node* Get(LinkList L, int i){
    Node *p;
    p=L;
    int j=0;//扫描定位
    while((p->next!=NULL)&&(j<i)){
        p=p->next;
        j++;
    }
    //到位了
    if(i==j) return p;
    else return NULL;
}

5、按值查找元素

//按值查找
Node* Locate(LinkList L, ElemType key){
    Node *p;
    p=L->next; //从第一个结点开始
    int j=0; //扫描定位
    while(p!=NULL){
        if(p->data!=key){
            p=p->next;
        }else{
            break;
        }
    }
    //到位了
    return p;
}

6、插入值

用pre指针定位到i-1前,然后插入算法即头插法

//在第i个元素前插入值e
void InsList(LinkList L, int i, ElemType e){
    Node *pre, *s;
    pre=L;
    int k=0;
    while((pre!=NULL)&&(k<i-1)){
        pre=pre->next;
        k=k+1;
    }
    //链长不足i-1
    if(k!=i-1){
        printf("Wrong position!");
        return;  
    }
    s=(Node*)malloc(sizeof(Node));
    s->data=e;
    //头插法
    s->next=pre->next;
    pre->next=s;   
}

7、删除结点

删除第i个结点

//删除第i个元素
int DelList(LinkList L, int i, ElemType *e){
    Node *pre=L, *r;
    int k=0;
    while((pre->next!=NULL)&&(k<i-1)){
        pre=pre->next;
        k++;
    }
    if(!(pre->next)||(i<1)){
        printf("Wrong position!");
        return (ERROR);
    }
    //此时pre已经到了i-1的位置
    r=pre->next;//r指向第i个位置
    pre->next=r->next;//pre指向第i+1个位置
    *e=r->data;//*e存放删除点数据
    free(r);//释放删除点r的内存空间
    return 0;
}

8、单链表长度

int ListLen(LinkList L){
    Node *p=L->next;
    int len=0;
    while(p!=NULL){
        p=p->next;
        len++;
    }
    return len;
}

9、合并两个有序非递减链表

//有序非递减链表合并
LinkList MergeLinkList(LinkList LA, LinkList LB){
    Node *pa=LA->next, *pb=LB->next;
    LinkList LC=LA;
    LC->next=NULL;
    r=LC;
    while(pa!=NULL&&pb!=NULL){
        if(pa->data<=pb->data){
            //尾插法
            r->next=pa;
            r=pa;
            pa=pa->next;
        }else{
            r->next=pb;
            r=pb;
            pb=pb->next;
        }
    }
    //LA还有剩,把LA后面的全部扔到LC后面即可
    if(pa) r->next=pa;
    if(pb) r->next=pb;
    return (LC);
}

循环链表

循环链表的合并

//两个循环单链表合并
LinkList merge1(LinkList LA, LinkList LB){
    Node *p=LA, *q=LB;
    //寻找LA LB的表尾存放指针p q中
    while(p->next!=LA) p=p->next;
    while(q->next!=LB) q=q->next;
    q->next=LA;
    p->next=LB->next;
    free(LB);
    return (LA); 
}

.

【数据结构】线性表总结(顺序表 单链表 双链表 循环链表)_第3张图片

双向链表的声明

双链表在操作上和单链表保持一致
【数据结构】线性表总结(顺序表 单链表 双链表 循环链表)_第4张图片

typedef struct Dnode{
    ElemType data;
    struct DNode *prior, *next;
}DNode, *DoubleList;

本文更新至2020.7.4


你可能感兴趣的:(数据结构)