数据结构---双链表以及链式栈

1. 双向链表

每个节点都有一个向后的指针和一个向前的指针

//DLlist.h
#ifndef _DOUBLELINKLIST_H_
#define _DOUBLELINKLIST_H_
#define ElementType int

typedef struct DoubleLinkList DLlist;
typedef struct Node  SNode;
struct Node
{
    ElementType data;
    SNode* next;
    SNode* prev;
};
struct DoubleLinkList
{
    SNode* head;
    SNode* tail;
    int len;
};

int InitDLlist(DLlist* list);
void InsertTail(DLlist* list,ElementType element);
void InsertHead(DLlist* list,ElementType element); 
void InsertIndex(DLlist* list,ElementType element,int index);
void RemoveIndex(DLlist* list,int index);
int FindFirstByElement(DLlist* list,ElementType element);//返回要找元素的下标
void RemoveElement(DLlist* list,ElementType element);
int* FindIndex(DLlist* list,int index);
int* FindElement(DLlist* list,ElementType element);
void SetIndex(DLlist* list,ElementType element,int index);
void SetElement(DLlist* list,ElementType oldelement,ElementType newelement);
void FreeDLlist(DLlist* list);
void Travel(DLlist* list);

#endif
//DLlist.c
#include<stdio.h>
#include<stdlib.h>
#include"DoubleLinkList.h"
#define true 1
#define false 0

int InitDLlist(DLlist* list)
{
    list->head=NULL;
    list->tail=NULL;
    list->len=0;
    return true;
}

SNode* CreateNode(ElementType element)
{
    SNode* NewNode=(SNode*)malloc(sizeof(SNode));
    if(NewNode==NULL)
    {
        printf("CreateNode malloc error\n");
        return NULL;
    }
    NewNode->next=NULL;
    NewNode->prev=NULL;
    NewNode->data=element;
    return NewNode;
}

void InsertTail(DLlist *list, ElementType element)
{
    SNode* NewNode=CreateNode(element);
    if(NewNode==NULL)
    {
        printf("InsertTail CreateNode error\n");
        return;
    }
    if(list->len==0)  //链表是空的情况,那么这个数既是头也是尾/***********************************************
                                                        /**********************************************/
    {
        list->head=NewNode;
        list->tail=NewNode;
    }  
    else  
   {
    list->tail->next=NewNode;
    NewNode->prev=list->tail; 
    list->tail=NewNode;
   }
   list->len++;
}

void InsertHead(DLlist *list, ElementType element)
{
     SNode* NewNode=CreateNode(element);
    if(NewNode==NULL)
    {
        printf("InsertTail CreateNode error\n");
        return;
    }
    if(list->len==0)  //链表是空的情况,那么这个数既是头也是尾
    {
        list->head=NewNode;
        list->tail=NewNode;
    }  
    else  
   {
    list->head->prev=NewNode;
    NewNode->next=list->head; 
    list->head=NewNode;  //将他设为新的头
   }
   list->len++;
}

void InsertIndex(DLlist *list, ElementType element, int index)
{
    if(index<0 ||index>list->len)
    {
        printf("Insert invalid place\n");
        return;
    }
    SNode* NewNode=CreateNode(element);
    if(NewNode==NULL)
    {
        printf("Insert  Create  error\n");
        return;
    }
    if(index==0)/*****************************************************************************************/
    {                                     
        InsertHead(list,element);
        return;
    }
    if(index==list->len)
    {
        InsertTail(list,element);
        return;
    }
    struct Node* TravelPoint = list->head;
    while(index != 0)
    {
        TravelPoint = TravelPoint->next;
        index--;
    }
    NewNode->prev=TravelPoint->prev;
    TravelPoint->prev->next=NewNode;
    NewNode->next=TravelPoint;
    TravelPoint->prev=NewNode;
    list->len++;
    return;
    
}

void RemoveIndex(DLlist *list, int index)/********************************************************************/
{  //三种情况:1 删的是头或者尾,那么头无前驱,尾无后继
   //        2 链表只有一个节点,无头无尾
   //        3 正常的中间那个节点
    if(index<0 || index >=list->len )
    {
        printf("Removeindex Invaild place!\n");
        return;
    }
    if(index==0)   //1 头
    {
        if(list->len==1)  //2
        {
            free(list->head);
            list->head=NULL;
            list->tail=NULL;
            list->len=0;
            return;
        }

        SNode* freenode=list->head; //记录下头以便释放
        list->head=list->head->next;
        list->head->prev=NULL;
        free(freenode);
        list->len--;
        return;
    }
    if(index==list->len-1)     //2 尾
    {
        SNode* freenode=list->tail; 
        list->tail=list->tail->prev;
        list->tail->next=NULL;
        free(freenode);
        list->len--;
        return;
    }
    // 3 正常
    SNode* TravelPoint=list->head;  
    while(index!=0)
    {
        TravelPoint=TravelPoint->next;
        index--;
    }
    SNode* PrevNode = TravelPoint->prev;
    SNode* NextNode = TravelPoint->next;
    PrevNode->next=NextNode;
    NextNode->prev=PrevNode;
    free(TravelPoint);
    list->len--;
}

int FindFirstByElement(DLlist *list, ElementType element)
{
    int count=0;  //下标
    SNode* TravelPoint=list->head;
    while(TravelPoint!=NULL)
    {
        if(TravelPoint->data==element)
        {
            return count;
        }
        count++;
        TravelPoint=TravelPoint->next;
    }
    return -1; //如果没找到,返回一个非法下标
}

void RemoveElement(DLlist *list, ElementType element)
{
    int index=FindFirstByElement(list,element);
    while(index!=-1)  //index!=-1说明还没找完
    {
        RemoveIndex(list,index);
        index=FindFirstByElement(list,element);
    }
}

int* FindIndex(DLlist *list, int index)
{
    if(index<0 || index >=list->len )
    {
        printf("Setindex Invaild place!\n");
        return NULL;
    }
    SNode* TravelPoint =list->head;
    while(index!=0)
    {
        TravelPoint=TravelPoint->next;
        index--;
    }
    return &TravelPoint->data;
}

int* FindElement(DLlist *list, ElementType element)
{
    int* array=(int*)malloc(sizeof(int)*list->len+1);
    if(array==NULL)
    {
        printf("FindElement Malloc Error\n");
        return NULL;
    }
    int count=0;
    int i=0;
    SNode* TravelPoint =list->head;
    while(TravelPoint!=NULL)
    {
        if(TravelPoint->data==element)
        {
            count++;
            array[count]=i;
        }
        i++;
        TravelPoint=TravelPoint->next;
    }
    array[0]=count;
    return array;
}

void SetIndex(DLlist *list, ElementType element, int index)
{
    if(index<0 || index >=list->len )
    {
        printf("Setindex Invaild place!\n");
        return;
    }
    SNode* TravelPoint =list->head;
    while(index!=0)
    {
        TravelPoint=TravelPoint->next;
        index--;
    }
    TravelPoint->data=element;
}

void SetElement(DLlist *list, ElementType oldelement, ElementType newelement)
{
    int index=FindFirstByElement(list,oldelement);
    while(index!=-1)
    {
        SetIndex(list,newelement,index);
        index=FindFirstByElement(list,oldelement);
    }
}

void FreeDLlist(DLlist *list)
{
    while(list->head!=NULL)  //每次放头,头指针指向的地址是空,意味着链表是空的
    {
        SNode* freenode=list->head;
        list->head=list->head->next;
        free(freenode);
    }
    list->tail=NULL;/*******************************************************************************************/
    list->len=0;
}

void Travel(DLlist *list)
{ //要保证从前往后的指针和从后往前的指针都没问题,所以要travel两次
    printf("len: %d \n",list->len);
    printf("next: ");
    SNode* TravelPoint=list->head;
    while(TravelPoint!=NULL)
    {
        printf("%d ",TravelPoint->data);
        TravelPoint=TravelPoint->next;
    }
    printf("\n");
    printf("prev: "); 
    TravelPoint=list->tail;
    while(TravelPoint!=NULL)
    {
        printf("%d ",TravelPoint->data);
        TravelPoint=TravelPoint->prev;
    }
    printf("\n");
}

 

2. 循环链表

首尾相连 (蓝色,看看即可)

//头文件与双向链表一致,DCLlist.c
#include<stdio.h>
#include<stdlib.h>
#include"DoubleCircleLinkList.h"
#define true 1
#define false 0

int InitDCLlist(DCLlist *list)
{
    list->head=NULL;
    list->tail=NULL;
    list->len=0;
    return true;
}

SNode* CreateNode(ElementType element)
{
    SNode* NewNode=(SNode*)malloc(sizeof(SNode));
    if(NewNode==NULL)
    {
        printf("CreateNode malloc error\n");
        return NULL;
    }
    NewNode->next=NULL;
    NewNode->prev=NULL;
    NewNode->data=element;
    return NewNode;
}

void InserTail(DCLlist *list, ElementType element)
{
    SNode* NewNode=CreateNode(element);
    if(NewNode==NULL)
    {
        printf("InsertTail CreateNode error\n");
        return;
    }
    if(list->len==0)  
    {
        list->head=NewNode;
        list->tail=NewNode;
    }  
    else  
   {
    list->tail->next=NewNode;
    NewNode->prev=list->tail; 
    list->tail=NewNode;

    //***********下面两句和双链表不一样,作用是首尾相连
    list->tail->next=list->head;
    list->head->prev=list->tail;
   }
   list->len++;
}

void InsertHead(DCLlist *list, ElementType element)//************
{       //先尾插,然后头尾指针前移
    InserTail(list,element);
    if(list->len>1)
    {
    list->tail=list->tail->prev; //先在尾巴后插入一个数然后头指针前移,假装是头插 
    list->head=list->head->prev;
    }
    
}

void RemoveIndex(DCLlist *list, int index)
{
    if(index<0 || index >=list->len )
    {
        printf("Removeindex Invaild place!\n");
        return;
    }
    if(index==0)   
    {
        if(list->len==1) 
        {
            free(list->head);
            list->head=NULL;
            list->tail=NULL;
            list->len=0;
            return;
        }

        SNode* freenode=list->head; 
        list->head=list->head->next;
        list->head->prev=list->tail;//**
        list->tail->next=list->head;//**
        free(freenode);
        list->len--;
        return;
    }
    if(index==list->len-1)     
    {
        SNode* freenode=list->tail; 
        list->tail=list->tail->prev;
        list->tail->next=list->head;//**
        list->head->prev=list->tail;//**
        free(freenode);
        list->len--;
        return;
    }
    
    SNode* TravelPoint=list->head;  
    while(index!=0)
    {
        TravelPoint=TravelPoint->next;
        index--;
    }
    SNode* PrevNode = TravelPoint->prev;
    SNode* NextNode = TravelPoint->next;
    PrevNode->next=NextNode;
    NextNode->prev=PrevNode;
    free(TravelPoint);
    list->len--;
}

void RemoveElement(DCLlist *list, ElementType element)
{
    int index=FindFirstByElement(list,element);
    while(index!=-1)  
    {
        RemoveIndex(list,index);
        index=FindFirstByElement(list,element);
    }
}

int FindFirstByElement(DCLlist *list, ElementType element)
{
    int count=0;  
    SNode* TravelPoint=list->head;
    while(TravelPoint!=list->tail)//**
    {
        if(TravelPoint->data==element)
        {
            return count;
        }
        count++;
        TravelPoint=TravelPoint->next;
    }
    if(list->tail!=NULL && list->tail->data==element)//**
    {
        return count;
    }
    return -1; //如果没找到,返回一个非法下标
}

void Travel(DCLlist *list)
{ 
    if(list->len==0)//**
    return;

    printf("len: %d \n",list->len);
    printf("next: ");
    SNode* TravelPoint=list->head;
    while(TravelPoint!=list->tail)//**头就是尾的时候
    {
        printf("%d ",TravelPoint->data);
        TravelPoint=TravelPoint->next;
    }
    printf("%d ",list->tail->data); //**
    printf("\n");

    printf("prev: "); 
    TravelPoint=list->tail;
    while(TravelPoint!=list->head)//**
    {
        printf("%d ",TravelPoint->data);
        TravelPoint=TravelPoint->prev;
    }
    printf("%d ",list->head->data); //**
    printf("\n");
}

void FreeDCLlist(DCLlist *list)
{
    if(list->len==0)//**
    return;

    while(list->head!=list->tail) //**头就是尾的时候
    {
        SNode* freenode=list->head;
        list->head=list->head->next;
        free(freenode);
    }

    free(list->head);  //**
    list->head=NULL;
    list->tail=NULL;
    list->len=0;
}

3. 约瑟夫环

#include<stdio.h>
#include<stdlib.h>
#include"DoubleCircleLinkList.h"
int main()
{
    DCLlist list;
    InitDCLlist(&list);
    for(int i=0;i<13;i++)
    {
        InserTail(&list,i+1);
    }
    Travel(&list);
 //   约瑟夫环
    int count=1;
    SNode* TravelPoint=list.head;
    while(list.len!=1)
    {
        if(count==3)
        {
            printf("%d is out!\n",TravelPoint->data);
            SNode* temp=TravelPoint->next;
            RemoveElement(&list,TravelPoint->data);
            TravelPoint=temp;
            count=0;
        }
        else{
            TravelPoint=TravelPoint->next;//***********************************************
        }
        count++;
        
    }
    printf("%d is alive\n",list.head->data);

    return 0;
}

4. 链式栈

线性表: 顺序表: 支持随机存取,插入和删除比较麻烦

链表: 插入和删除比较方便,不利于随机存取

链式栈

//LinkStack.h
#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_
#include"DoubleLinkList.h"
struct LinkStack  //栈结构体
{
    DLlist stack;   //用这个双链表来做栈
     ElementType TopElement; //栈顶元素
};
typedef struct LinkStack LStack;

int InitLStack(LStack* s);
void Push(LStack* s,ElementType element);
ElementType* Pop(LStack* s);
SNode* GetTop(LStack *s);//能访问栈顶指针的接口
int IsEmpty(LStack* s);
void StackTravel(LStack*s);
#endif

 

//LinkStack.c
#include<stdio.h>
#include "LinkStack.h"
#define true 1
#define false 0
int InitLStack(LStack *s)
{
    return InitDLlist(&s->stack); 
}

void Push(LStack *s, ElementType element)
{   //链式结构除非把堆上空间申请满了,不然不会栈满
    InserTail(&s->stack,element);//先进来的在最下面,就是  尾插
}

ElementType* Pop(LStack *s)
{
    if(s->stack.len==0)
    {
        printf("the stack is empty\n");
        return NULL;
    }
    s->TopElement=s->stack.tail->data; //栈顶是链表尾部
    RemoveIndex(&s->stack,s->stack.len-1);
    return &s->TopElement;
}

SNode *GetTop(LStack *s)
{
    return s->stack.tail;  //尾指针充当栈顶指针
}

int IsEmpty(LStack *s)
{
    if(s->stack.len==0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void StackTravel(LStack *s)
{
    Travel(&s->stack);
}

5. 栈的运用:数值运算

#include <stdio.h>
#include<stdlib.h>
#include "LinkStack.h"
#define true 1
#define false 0
int IsNum(char c)
{
    if(c<='9'&& c>='0')
    {
        return true;
    }
    else
    {
        return false;
    }
}
int IsOper(char c)
{
    switch(c)
    {
        case '+':
        case '-':
        case '*':
        case '/':
        case '(':
        case ')':
        case '=':
            return true;
        default:
            return false;
    }
}
int Operate(int prev,int next,char symbol) //计算
{
    switch(symbol)
    {
        case'+':  return prev+next;
        case'-':  return prev-next;
        case'*':  return prev*next;
        case'/':  
        if(next==0)  //除数不能为0
        {
            printf("device zero!\n");
            exit(-1);  //exit函数的作用是退出程序-1代表非法退出
        }
        return prev/next;
        default:
            break;
    }
}
int Precede(char ch1,char ch2)//运算符优先级比较
{//行是栈顶元素,列是将要入栈元素,都是加减乘除左右括号和等号
    char pre[7][7]=   
    {
        {'>','>','<','<','<','>','>'},
        {'>','>','<','<','<','>','>'},
        {'>','>','>','>','<','>','>'},//5,7 是( =不可能存在,垃圾值
        {'>','>','>','>','<','>','>'},//5,6 是这种情况(9)无意义
        {'<','<','<','<','<','=','0'},//5,1的情况是栈顶为(,将入栈是+就是类似1-(2+3)此时右边的+比(优先级高
        {'>','>','>','>','0','>','>'},
        {'0','0','0','0','0','0','='}
    };
    int i=0,j=0;
    switch(ch1)
    {
        case'+': i=0;break;
        case'-': i=1;break;
        case'*': i=2;break;
        case'/': i=3;break;
        case'(': i=4;break;
        case')': i=5;break;
        case'=': i=6;break;
        default:
            break;
    }
    switch(ch2)
    {
        case'+': j=0;break;
        case'-': j=1;break;
        case'*': j=2;break;
        case'/': j=3;break;
        case'(': j=4;break;
        case')': j=5;break;
        case'=': j=6;break;
        default:
            break;
    }
    return pre[i][j];
}

int main()
{
    // LStack stack;
    // InitLStack(&stack);
    // for(int i=0;i<10;i++)
    // {
    //     Push(&stack,i+1);
    // }
    // while(GetTop(&stack)!=NULL)//尾指针是空时,栈空
    // {
    //     printf("%d ",*Pop(&stack));
    // }
    // printf("\n");



//+-*/
    LStack Num;
    InitLStack(&Num);
    LStack Oper;
    InitLStack(&Oper);
    char str[100]={0}; //字符
    printf("please input !\n");
    scanf("%[^\n]",str);  //识别的输入字符直到换行为止
    int i=0;   //i是str[]的元素下标
    while(str[i]!='\0')
    {
        if(IsOper(str[i])==true)
        {
            if(IsEmpty(&Oper)==true)
            {
                Push(&Oper,str[i]);
                i++;
            }
            else
            {
                char symbol = Precede(GetTop(&Oper)->data,str[i]);
                switch (symbol)
                {
                case '<' :
                    Push(&Oper,str[i]);
                    i++;
                    break;
                case '>' :
                    int next=*Pop(&Num);
                    int prev=*Pop(&Num);
                    char s=*Pop(&Oper);
                    Push(&Num,Operate(prev,next,s));
                    break;
                case '=':  //无意义
                    Pop(&Oper); 
                    i++;
                    break;
                default:
                    break;
                }
            }
        }
        else if(IsNum(str[i]))
        {
            int num=str[i]-'0';
            Push(&Num,num);
            i++;
            while(IsNum(str[i]))
            {
                int higher=*Pop(&Num);
                Push(&Num,higher*10+str[i]-'0');
                i++;
            }
        }
        
        else if(str[i]==' ')
        {
            while(str[i]==' ')
            {
                i++;
            }

        }
    }
    printf(" the answer is %d \n",GetTop(&Num)->data);

    return 0;
}

6. 队列

先进先出

//Queue.h
#ifndef _QUEUE_H_
#define _QUEUE_H_
#include"DoubleLinkList.h"
struct LinkQueue
{
    DLlist queue;
    ElementType FrontData;
};
typedef struct LinkQueue LQueue;

int InitLQueue(LQueue *lq);
void QPush(LQueue* lq,ElementType element);
ElementType* QPop(LQueue* lq);
int IsQEmpty(LQueue* lq);
SNode* GetFront(LQueue* lq);
void FreeQueue(LQueue* lq);
#endif
//Queue.c
#include<stdio.h>
#include<stdlib.h>
#include "Queue.h"
#define true 1
#define false 0

int InitLQueue(LQueue *lq)
{
    return InitDLlist(&lq->queue);
}

void QPush(LQueue *lq, ElementType element)
{
    InsertTail(&lq->queue,element);
}

ElementType* QPop(LQueue *lq)
{
    if(lq->queue.len==0)
    {
        printf("queue is empty\n");
        return NULL;
    }
    lq->FrontData=lq->queue.head->data;
    RemoveIndex(&lq->queue,0);
    return &lq->FrontData;   
}

int IsQEmpty(LQueue *lq)
{
    if(lq->queue.len==0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

SNode *GetFront(LQueue *lq)
{
    return lq->queue.head;
}

void FreeQueue(LQueue *lq)
{
    FreeDLlist(&lq->queue);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值