《数据结构》C语言

一. 线性表

1.顺序表

特点:逻辑上相邻,物理上也相邻,存取方便

#include<stdio.h>
#include<stdlib.h>
#define ElemType int //元素类型
#define Status int //函数类型
#define List_Size 100 // 存储空间初始量
#define List_Increase 10 // 存储空间增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef struct SqList {
    ElemType *elem; // 数据元素存储空间的首地址
    int length, listsize; // 线性表的当前长度和存储容量
}S;

Status Init_List(SqList &L);//构造一个空线性表
Status Destroy_List(SqList &L);//销毁线性表
Status Clear_List(SqList &L);//重置为空表
Status ListEmpty(SqList L);//表空true,否则false
Status ListLength(SqList L);//L中元素个数
Status ListInsert(SqList &L, int i, ElemType e);//在第i个位置前插入元素e
Status ListDel(SqList &L, int i, ElemType &e);//删除第i个元素,返回其值
Status GetElem(SqList L, int i, ElemType &e);//用e放回第i个元素的值
Status LocateElem(SqList L, ElemType e, Status(*compare)(ElemType, ElemType));//返回第一个与e满足compare关系的元素位序


int main()
{
    SqList L;
    Init_List(L);
    for(int i = 1; i <= 5; i ++)
        ListInsert(L, 1, i);

    for(int i = 1; i <= 5; i ++)
        printf("%d ", *(L.elem + i - 1));
    return 0;
}

Status Init_List(SqList &L){
    L.elem = (ElemType*)malloc(List_Size*sizeof(ElemType));//分配空间并返回第一个字节地址
//L.elem = new ElemType[List_size];
    if(!L.elem) exit(OVERFLOW);
    L.length = 0;
    L.listsize = List_Size;
    return OK;
}

Status Destroy_List(SqList &L){
    free(L.elem);//释放内存
    L.elem = NULL;
    L.length = 0;
    L.listsize = 0;
    return OK;
}

Status Clear_List(SqList &L){
    L.length = 0;
    return OK;
}

Status List_Empty(SqList L){
    if(L.length == 0) return TRUE;
    else return FALSE;
}

Status ListLength(SqList L){
    return L.length;
}

Status ListInsert(SqList &L, int i, ElemType e){
    if(i < 1 || i > L.length + 1) return ERROR;//i不合法
    if(L.length >= L.listsize){//存储空间满,增加分配
        ElemType *newbase = (ElemType*) realloc (L.elem, (L.listsize + List_Increase)*sizeof(ElemType));
        if(!newbase) exit(OVERFLOW);
        L.elem = newbase;
        L.listsize += List_Increase;
    }

    ElemType *q;
    ElemType *p;
    q = L.elem + i - 1; //插入位置
  //q = &(L.elem[i - 1]);

    //往后移
    for(p = &(L.elem[L.length - 1]); p >= q; p --){
        *(p + 1) = *p;
    }

    *q = e;
    L.length ++;
}

Status ListDel(SqList &L, int i, ElemType &e){
    if(i < 1 || i > L.length) return ERROR;

    ElemType *q, *p;
    q = L.elem + i - 1;//删除位置
    e = *q;//删除元素的值
    p = L.elem + L.length - 1;
    for(q ++; q <= p; q ++){ //i后面的左移
        *(q - 1) = *q;
    }
    L.length --;
    return OK;
}

Status GetElem(SqList L, int i, int &e){
    if(i < L.length || i > L.length) exit(ERROR);
    e = *(L.elem + i - 1);
    return OK;
}

Status LocateElem(SqList L, ElemType e, Status(*compare)(ElemType, ElemType)){
    int i = 1;
    ElemType *q;
    q = L.elem;
    while(i <= L.length && !compare(*q ++, e)){
        i ++;
    }
    if(i <= L.length) return i;
    else return 0;
}

2.链表

特点:逻辑上相邻,物理上不一定相邻,插删方便
(*a).b 等价于 a->b

#include<stdio.h>
#include<stdlib.h>
#define ElemType int //元素类型
#define Status int //函数类型
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef struct LNode {
    ElemType data;  //数据域
    struct LNode *next;  //指针域
} LNode, *LinkList;

Status InitList(LinkList &L); //构造一个空的单链表
Status DestroyList(LinkList &L); //销毁顺序线性表L
Status ClearList(LinkList &L); //单链表清空
Status ListEmpty(LinkList L); //单链表判空
int ListLength(LinkList L); //求链表长度
Status GetElem(LinkList L, int i, ElemType &e); //取单链表中位序为i的元素值
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType,ElemType)); //定位操作,返回L中第1个与e满足关系compare()的数 据元素的位序。若未找到则返回0
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e); //求前驱操作
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e); //求后继操作
Status ListInsert(LinkList &L, int i, ElemType e); //在L中第i个位置之前插入新的数据元素e
Status ListDelete(LinkList L, int i, ElemType &e); //在L中删除第i个位置元素,由e返回其值
Status comp(ElemType c1,ElemType c2); //数据元素判定函数(相等为TRUE,否则为FALSE)
void display(LinkList L); //遍历

int main()
{
    LinkList L; //单链表的头指针
    InitList(L);
    for(int i = 1; i <= 5; i ++)
        ListInsert(L, 1, i);
    display(L);
    return 0;
}

Status InitList(LinkList &L)
{
    L = (LinkList)malloc(sizeof(struct LNode)); //产生头结点,并使L指向此头结点
    if(!L) // 存储分配失败
        exit(OVERFLOW);
    L -> next = NULL; // 指针域为空
    return OK;
}

Status DestroyList(LinkList &L)
{
    LinkList q;
    while(L)
    {
        q = L -> next;
        free(L);
        L = q;
    }
    return OK;
}

Status ClearList(LinkList &L)
{ // 初始条件:线性表L已存在。操作结果:将L重置为空表
    LinkList p, q;
    p = L -> next; // p指向第一个结点
    while(p) // 没到表尾
    {
        q = p -> next;
        free(p);
        p = q;
    }
    L -> next = NULL; // 头结点指针域为空
    return OK;
}

Status ListEmpty(LinkList L)
{
    if(L-> next) // 非空
        return FALSE;
    else
        return TRUE;
}

int ListLength(LinkList L){
    int n = 0;
    LinkList p = L -> next;
    while(p){
        n ++;
        p = p -> next;
    }
    return n;
}

Status ListInsert(LinkList &L, int i, ElemType e){
    LinkList p = L;
    int j = 0;
    while(p && j < i - 1){
        p = p -> next;
        j ++;
    }
    if(!p || j > i - 1) return ERROR;
    LinkList s = (LinkList) malloc (sizeof(LNode));
    s -> data = e;
    s -> next = p -> next;
    p -> next = s;
    return OK;
}

Status ListDelete(LinkList L, int i, ElemType &e)
{ /* 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */
    int j = 0;
    LinkList p = L, q;
    while(p -> next && j < i - 1) // 寻找第i个结点,并令p指向其前趋
    {
        p = p -> next;
        j ++;
    }
    if(!p -> next || j > i-1) /* 删除位置不合理 */
        return ERROR;
    q = p -> next; /* 删除并释放结点 */
    p -> next = q -> next;
    e = q -> data;
    free(q);
    return OK;
}

void display(LinkList head)
{
    LinkList p = head->next;
    while(p != NULL)			//注意陈列打印的条件
    {
        printf("%d ", p -> data);
        p = p -> next;
    }
    return;
}

Status GetElem(LinkList L, int i, ElemType &e) /* 算法2.8 */
{
    int j = 1; // j为计数器
    LinkList p = L -> next; // p指向第一个结点
    while(p && j < i) // 顺指针向后查找,直到p指向第i个元素或p为空
    {
        p = p -> next;
        j ++;
    }
    if(!p || j > i) // 第i个元素不存在
        return ERROR;
    e = p -> data; // 取第i个元素
    return OK;
}


Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{
    // 操作结果: 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, 返回OK;否则操作失败,pre_e无定义,返回INFEASIBLE
    LinkList q, p = L -> next; // p指向第一个结点
    while(p -> next) // p所指结点有后继
    {
        q = p -> next; // q为p的后继
        if(q -> data == cur_e)
        {
            pre_e = p -> data;
            return OK;
        }
        p = q; //p向后移
    }
    return INFEASIBLE;
}

Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{
    // 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,返回OK;否则操作失败,next_e无定义,返回INFEASIBLE
    LinkList p = L -> next; // p指向第一个结点
    while(p -> next) // p所指结点有后继
    {
        if(p -> data == cur_e)
        {
            next_e = p -> next -> data;
            return OK;
        }
        p = p -> next;
    }
    return INFEASIBLE;
}

int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType)){
    int i = 0;
    LinkList p = L -> next;
    while(p){
        i ++;
        if(compare(p -> data, e)) return i;
        p = p -> next;
    }
    return ERROR;
}

Status comp(ElemType c1, ElemType c2)
{ /* 数据元素判定函数(相等为TRUE,否则为FALSE) */
    if(c1 == c2)
        return TRUE;
    else
        return FALSE;
}

二. 栈和队列

1.队列

//头节点不存数据,便于操作
#include <stdio.h>
#include<malloc.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;

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

typedef struct LinkQueue{
    LinkList front, rear; //对头队尾指针
}LinkQueue;


//如果不能用引用,形参用指针类型,(LinkQueue *Q), 函数中的前也要加*,下面函数中的e也一样
Status InitQueue(LinkQueue &Q){ //初始化
    Q.front = Q.rear = (LinkList) malloc(sizeof(LNode)); //强转为LinkList指针
    if(!Q.front) exit(OVERFLOW);
    Q.front -> next = NULL;
    return OK;
}

Status DestroyQueue(LinkQueue &Q){ //销毁
    while(Q.front){ //非空
        LinkList p = Q.front -> next;
        free(Q.front);
        Q.front = p;
    }
    return OK;
}

Status QueueInsert(LinkQueue &Q, ElemType e){ //入队
    LinkList p = (LinkList)malloc(sizeof(LNode));
    if(!p) exit(OVERFLOW);
    p -> data = e;
    p -> next = NULL;
    Q.rear -> next = p; //入队,把p接在后面
    Q.rear = p; //把队尾更新
    return OK;
}

Status DeQueue(LinkQueue &Q, ElemType &e){ //出队
    if(Q.front == Q.rear) return ERROR;
    LinkList p = Q.front -> next;
    e = p -> data;
    Q.front -> next = p -> next; //ne[idx] = ne[ne[idx]]那个意思;
    if(Q.rear == p) Q.rear = Q.front; //要出队的对头已经是最后一个元素了
    free(p); //c++可以delete p;
    return OK;
}

Status GetHead(LinkQueue &Q, ElemType &e){ //获取对头,不出队
    if(Q.rear == Q.front) return ERROR;
    e = Q.front -> next -> data;
    return OK;
}

int QueueLength(LinkQueue &Q){
    int len = 0;
    LinkList p;
    if(Q.front == Q.rear) return 0;
    p = Q.front -> next;
    while(p){
        len ++;
        p = p -> next;
    }
    return len;
}

Status visit(LinkQueue Q){
    if(Q.front == Q.rear) return ERROR;
    LinkList p = Q.front -> next;
    while(p){
        printf("%d ", p -> data);
        p = p -> next;
    }
    return OK;
}

int main()
{
    LinkQueue Q;
    InitQueue(Q); //形参用的指针类型的话,传入要加引用
    for(int i = 1; i <= 3; i ++) QueueInsert(Q, i);
    visit(Q);
    printf("\n");
    printf("len: %d\n", QueueLength(Q));
    int x;
    DeQueue(Q, x);
    printf("first: %d\n", x);
    return 0;
}

2.栈

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#define ElemType int //元素类型
#define Status int //函数类型
#define Init_Size 100 // 存储空间初始量
#define Stack_Increase 10 // 存储空间增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef struct{
    ElemType *base, *top;
    int stacksize;
}SqStack;

Status InitStack(SqStack &S); //构造一个空栈
Status StackEmpty(SqStack S); //栈空,返回true
Status StackLength(SqStack S);
Status GetTop(SqStack S, ElemType &e); // 取栈顶,不pop
Status Push(SqStack &S, ElemType &e);
Status Pop(SqStack &S, ElemType &e);

int main()
{
    SqStack S;
    InitStack(S);
    for(int i = 1; i <= 5; i ++)
        Push(S, i);
    while(!StackEmpty(S)){
        int e;
        GetTop(S, e);
        Pop(S, e);
        printf("%d ", e);
    }
}

Status InitStack(SqStack &S){
    S.base = (ElemType *)malloc(Init_Size * sizeof(ElemType));
    if(!S.base) exit(OVERFLOW);

    S.top = S.base;
    S.stacksize = Init_Size;
    return OK;
}

Status GetTop(SqStack S, ElemType &e){
    if(S.top == S.base) return ERROR;
    e = *(S.top - 1);
    return OK;
}

Status StackEmpty(SqStack S){
    return S.base == S.top ? OK : ERROR;
}

Status StackLength(SqStack S){
    if(S.base == S.top)
        return 0;
    else
        return S.top - S.base;
}

Status Push(SqStack &S, ElemType &e){
    if(S.top - S.base >= S.stacksize){ //栈满,分配空间
        S.base = (ElemType *)realloc(S.base, (S.stacksize + Stack_Increase) * sizeof(ElemType));
        if(!S.base) exit(OVERFLOW);

        S.top = S.base + S.stacksize;
        S.stacksize += Stack_Increase;
        return OK;
    }

    *S.top ++ = e; //*S.top = e, S.top ++;
    return OK;
}

Status Pop(SqStack &S, ElemType &e){
    if(S.top == S.base) return ERROR; //栈空
    e = * --S.top; //S.top --, e = *S.top
    return OK;
}

三. 树和二叉树

1.二叉树

先序遍历构建二叉树,前中后序遍历(递归)

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#define TRUE       1
#define FALSE      0
#define OK         1
#define ERROR      0
#define OVERFLOW   -1
#define INFEASIBLE -2
#define NULL  0
#define Status int
#define ElemType char

typedef struct BiTNode{
    ElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

BiTree CreatBiTree()
{
    ElemType ch;
    scanf("%c", &ch);
    BiTree T;
    if(ch == '#') T = NULL;
    else{
        T = (BiTree)malloc(sizeof(BiTNode));
        if(!T) exit(OVERFLOW);
        T -> data = ch;
        T -> lchild = CreatBiTree();
        T -> rchild = CreatBiTree();
    }
    return T; //返回根节点
}

void Pre(BiTree T){
    if(T){
        printf("%c ", T -> data);
        if(T -> lchild) Pre(T -> lchild);
        if(T -> rchild) Pre(T -> rchild);
    }
}

void Mid(BiTree T){
    if(T){
        if(T -> lchild) Mid(T -> lchild);
        printf("%c ", T -> data);
        if(T -> rchild) Mid(T -> rchild);
    }
}

void Post(BiTree T){
    if(T){
        if(T -> lchild) Post(T -> lchild);
        if(T -> rchild) Post(T -> rchild);
        printf("%c ", T -> data);
    }
}

int main()
{
    BiTree T;
    T = CreatBiTree();
    Pre(T);
    printf("\n");
    Mid(T);
    printf("\n");
    Post(T);
}

非递归遍历
——待更新——

由前中或中后创建二叉树
——待更新——

2.哈夫曼树

哈夫曼树的结点的度数为0或2,没有度为1的结点
包含n颗树的森林要经过n - 1次合并形成哈夫曼树,共产生n - 1个新节点,所以包含n个叶子结点的哈夫曼树中共有2n - 1个结点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值