C语言之常用数据结构

目录

 

一、顺序表

二、单链表

三、双向链表

三、顺序栈

四、循环队列

五、二叉树


一、顺序表

顺序表是线性表的顺序存储,通过一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。假定线性表的元素类型为ElemType,则线性表的顺序存储类型描述为:

    //静态分配
    #define MaxSize 50
    typedef int ElemType;
    typedef struct{
	    ElemType data[MaxSize];
	    int length;
    }SqList;

C语言中一维数组可以进行动态分配避免溢出;

(1)插入操作

    bool ListInsert(SqList &L,int i,ElemType e){
        //在顺序表L的第i(1<=i<=L.length+1)个位置插入新元素e
	    if(i<1 || i>L.length+1)
	    	return false;
	    if(L.length>=MaxSize)
		    return false;
	    for(int j=L.length;j>=i;j--)            //将第i个元素及之后的元素后移
		    L.data[j]=L.data[j-1];
	    L.data[i-1]=e;
	    L.length++;
	    return true;
    } 

(2)删除操作

    bool ListDelete(SqList &L,int i, ElemType &e){
    //删除顺序表L中第i个未知的元素
	if(i<1 || i>L.length)
		return false;
	e=L.data[i-1];
	for(int j=i;j<L.length;j++)
		L.data[j-1]=L.data[j];
	L.length--;
	return true;
    }

(3)按值查找

    bool LocateElem(SqList &L,ElemType e){
    //查找顺序表中值为e的元素,查找成功则返回元素位置,否则返回0
	int i;
	for(int i=0;i<L.length;i++)
		if(L.data[i]==e)
			return i+1;
	return 0;
    }

 

二、单链表

单链表是线性表的链式存储,通过一组任意的储存单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表节点,除存放元素自身的信息外,还需要存放一个指向其后继的指针。单链表中的节点类型如下:

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

通常用头指针来标识一个单链表,此外为了操作上的方便,在单链表第一个节点之前附加一个结点,称为头结点。

(1)建立单链表

    LinkList CreatList1(LinkList &L){ 
    //头插法建立单链表
	LNode *s;int x;
	L=(LinkList)malloc(sizeof(LNode));
	L->next=NULL;
	scanf("%d",&x);
	while(x!=9999){
		s=(LNode*)malloc(sizeof(LNode));
		s->data=x;
		s->next=L->next;
		L->next=s;
		scanf("%d",&x);
	}
	return L;
    } 

    LinkList CreatList2(LinkList &L){
    //尾插法建立单链表
	int x;
	L=(LinkList)malloc(sizeof(LNode));
	LNode *s,*r=L;
	scanf("%d",&x);
	while(x!=9999){
		s=(LNode*)malloc(sizeof(LNode));
		s->data=x;
		r->next=s;
		r=s;
		scanf("%d",&x);
	}
	r->next=NULL;
	return L;
    } 

(2)按序号查找节点值

    LNode *GetElem(LinkList L,int i){
    //取出单链表L(带头节点)中第i个位置的结点指针
	    int j=1;
	    LNode *p=L->next;
	    if(i==0)
		    return L;
	    if(i<1)
		return NULL;
	    while(p&&j<i){
		    p=p->next;
		    j++;
	    }
	    return p;
    }

(3)按值查找表结点

    LNode *LocateElem(LinkList L,ElemType e){
    //查找单链表L(带头结点)中数据值等于e的结点指针,否则返回NULL
	    LNode *p=L->next;
	    while(p!=NULL&&p->data!=e)
		    p=p->next;
	    return p;
    }

(4)插入结点

    bool ListFrontInsert(LinkList L,int i,ElemType e){
    //将值为x的新节点插入到单链表的第i个位置桑
	LinkList p=GetElem(L,i-1);
	    if(NULL==p){
		    return false;
	    }
	    LinkList s=(LNode*)malloc(sizeof(LNode));
	    s->data=e;
	    s->next=p->next;
	    p->next=s;
	    return true;
    }

三、双向链表

双向链表在单链表的基础上增加了一个指向其前驱的prior指针,结点类型及相关函数描述如下:

    typedef int ElemType;
    typedef struct DNode{
	    ElemType data;
	    struct DNode *prior,*next;
    }DNode,*DLinkList;

    DLinkList Dlist_head_insert(DLinkList &DL){ 
    //头插法
	DNode *s;int x;
	DL=(DLinkList)malloc(sizeof(DNode));
	DL->next=NULL;
	DL->prior=NULL;
	scanf("%d",&x);
	while(x!=9999){
		s=(DNode*)malloc(sizeof(DNode));
		s->data=x;
		s->next=DL->next;
		if(DL->next!=NULL){
			DL->next->prior=s;
		}
		s->prior=DL;
		DL->next=s;
		scanf("%d",&x);
	}
	return DL;
    } 

    DLinkList Dlist_tail_insert(DLinkList &DL){
    //尾插法
	int x;
	DL=(DLinkList)malloc(sizeof(DNode));
	DNode *s,*r=DL;
	DL->prior=NULL;
	scanf("%d",&x);
	while(x!=9999){
		s=(DNode*)malloc(sizeof(DNode));
		s->data=x;
		r->next=s;
		s->prior=r;
		r=s;
		scanf("%d",&x);
	}
	r->next=NULL;
	return DL;
    } 

    DNode *GetElem(DLinkList DL,int i){
    //返回第i个位置的结点指针
	int j=1;
	DNode *p=DL->next;
	if(i==0)
		return DL;
	if(i<1)
		return NULL;
	while(p&&j<i){
		p=p->next;
		j++;
	}
	return p;
    }
    
    bool DListFrontInsert(DLinkList DL,int i,ElemType e){
    //插入结点
	DLinkList p=GetElem(DL,i-1);
	if(NULL==p){
		return false;
	}
	DLinkList s=(DNode*)malloc(sizeof(DNode));
	s->data=e;
	s->next=p->next;
	p->next->prior=s;
	s->prior=p;
	p->next=s;
	return true;
    }
    
    bool DListDelete(DLinkList DL,int i){
    //删除第i个结点
	DLinkList p=GetElem(DL,i-1);
	if(NULL==p){
		return false;
	}
	DLinkList q;
	q=p->next;
	if(q==NULL)
		return false;
	p->next=q->next;
	if(q->next!=NULL){ //删除最后一个元素,需要的判断 
		q->next->prior=p;
	}
	free(q);
	return true;
    }

三、顺序栈

顺序栈是采用顺序存储的栈,它利用一组地址连续的储存单元存放自栈底到栈顶的数据元素,同时设一个指针top指示当前栈顶位置。

    //实现栈 可以用数组,也可以用链表 
    #define MaxSize 50
    typedef int ElemType;
    typedef struct {
        ElemType data[MaxSize];
        int top;
    }SqStack;
    
    typedef struct LinkNode{
        ElemType data;
        struct LinkNode *next;
    }*LiStack;

    void InitStack(SqStack &S){
    //初始化
	S.top=-1;
    }

    bool StackEmpty(SqStack &S){
    //栈判空
	if(S.top==-1)
		return true;
	else
		return false;
    }

    bool Push(SqStack &S,ElemType x){
    //进栈
	if(S.top==MaxSize-1){
		return false;
	}
	S.data[++S.top]=x;
	return true;
    }

    bool Pop(SqStack &S,ElemType &x){
    //出栈
	if(-1==S.top)
		return false;
	x=S.data[S.top--];
	return true;
    }

    bool GetTop(SqStack &S,ElemType &x){
    //读取栈顶元素
	if(-1==S.top)
		return false;
	x=S.data[S.top];
	return true;
    }

四、循环队列

循环队列是将顺序队列臆造为一个环状空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。

顺序队列结点类型描述如下:

    //队列可以用数组也可用链表实现 
    #define MaxSize 5
    typedef int ElemType;
    typedef struct{
	    ElemType data[MaxSize];
	    int front,rear;
    }SqQueue;

    void InitQueue(SqQueue &Q) {
    //初始化
	    Q.rear=Q.front=0;
    }

    bool isEmpty(SqQueue &Q) {
    //判队空
	    if(Q.rear==Q.front)
		    return true;
	    else	
		    return false;
    } 

    bool EnQueue(SqQueue &Q,ElemType x){
    //入队
	    if((Q.rear+1)%MaxSize==Q.front)
		    return false;
	    Q.data[Q.rear]=x;
	    Q.rear=(Q.rear+1)%MaxSize;
	    return true;
    }

    bool DeQueue(SqQueue &Q,ElemType &x){
    //出队
	    if(Q.rear==Q.front)
		    return false;
	    x=Q.data[Q.front];
	    Q.front=(Q.front+1)%MaxSize; 
	    return true;
}

链式队列描述如下:

    typedef int ElemType;
    typedef struct LinkNode{
	    ElemType data;
	    struct LinkNode *next;
    }LinkNode;
    typedef struct{
	    LinkNode *front,*rear;
    }LinkQueue;
      
    void InitQueue(LinkQueue &Q){
    //初始化
	    Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
	    Q.front->next=NULL; 
    }

    bool IsEmpty(LinkQueue &Q){
    //判队空
	    if(Q.front==Q.rear)
		    return true;
	    else
		    return false;
    }

    void EnQueue(LinkQueue &Q,ElemType x){
    //入队
	    LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
	    s->data=x;s->next=NULL;
	    Q.rear->next=s;
	    Q.rear=s;
    }

    bool DeQueue(LinkQueue &Q,ElemType &x){
    //出队
	    if(Q.front==Q.rear) return false;
	    LinkNode *p=Q.front->next;
	    x=p->data;
	    Q.front->next=p->next;
	    if(Q.rear==p)
		    Q.rear=Q.front;
	    free(p);
	    return true;
    }

五、二叉树

     //链式存储
     typedef struct BiNode
     {
         char data;
         struct BiTNode *lchild,*rchild;
      }BiNode,*BiTree;
     //前中后序遍历
    void Inorder(BiTree T){
        if(T == NULL) return ;
        Inorder(T->lchild);
        // visit(T->data);
        printf("%c ", T->data);
        Inorder(T->rchild);
    }

    void preorder(BiTree T){
        if(T == NULL) return ;
        // visit(T->data);
        printf("%c ", T->data);
        Inorder(T->lchild);
        Inorder(T->rchild);
    }

    void postorder(BiTree T){
        if(T == NULL) return ;
        Inorder(T->lchild);
        Inorder(T->rchild);
        // visit(T->data);
        printf("%c ", T->data);
    }    
    //层次遍历
    void leverorder(BiTree BT){
        InitQueue(Q);
        BiTree P;
        EnQueue(Q,BT);
        while(!IsEmpty(Q){
            DeQueue(Q,P);
            visit(P);
            if(p->lchild!=NULL)
                EnQueue(Q,p->lchild);
            if(p->rchild!=NULL)
                EnQueue(Q,p->rchild);
            }
        }   
    }
    //非递归
    void inorder(BiTree T){
        InitStack(S);
        BiNode *p = T;
        while(!StackEmpty(S) || p){
            if(!p) {
                Push(S, p);
                p = p->lchild;
            }else {
                Pop(S, p);
                printf("%c ", p->data);
                p = p->rchild;
            }
        }
    }

    void postorder(BiTree T){
        InitStack(S);
        BiNode *p = T, *last = NULL;
    while(!StackEmpty(S) || p){
        if(p){
            Push(S, p);
            p = p->lchild;
            }
            else {
                GetTop(S, p);
                if(p->rchild && p == last){ // 向右子树 递归
                    Pop(S, p);
                    printf("%c ", p->data);
                    last = p;
                    p = NULL;
                }else {
                    p = p->rchild;
                }
            }
        }
    }

 

  • 5
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值