一、链表:链式结构的线性表
链表的节点:链表存放的数据内存
节点到组成:你存储的数据+链子(指针)的组合
1、单链表的逆序:
struct Node
{
int data; //存储变量区
struct Node *next; //因为链表是单向的,创建一个结构体指针指向下一个节点
};
struct LinkList
{
struct Node *head; //标记该链表的头地址,用来寻找整个链表
int len; //储存链表的长度
};
第一种方法:(利用三个变量)
void Reserve(struct LinkList *list)
{
struct Node *prev=NULL;
struct Node *cur=list->head; //定义cur指向首地址
struct Node *Next=list->head->next; //定义Next指向首地址的下一位
while(Next!=NULL) //当Next指向空的时候,结束循环
{
cur->next=prev; //cur指向下一个节点的指针指向prev
prev=cur; //将cur的值赋值给prev
cur=Next; //cur指向下一个节点
Next=cur->next; //Next指向下一个节点
}
cur->next=prev; //再将最后一个节点的指针指向上一个节点
list->head=cur; //将首地址指向cur,至此链表倒序结束
}
第二种方法(用递归的思想解决)
struct Node *Reserve2(struct Node *node)
{
struct Node *tail; //定义结构体指针作为尾指针
if(node->next==NULL) //当node的next指向空时,结束递归,返回node
{
return node;
}
else
{
tail=Reserve2(node->next); //进行递归操作,直到返回值
node->next->next=node; //将node的next指针指向的节点指向的下一位指向node
node->next=NULL; //将node的下一位指向空
return tail; //返回tail,实际上一直返回的是最后一次时返回的node,作为链表逆序后的首地址
}
}
2、双向链表:带双向头指针的链表
struct Node
{
ElementType data;
struct Node* next;
struct Node* prev;
};
struct DLinkList
{
struct Node *head;
struct Node *tail;
int len;
};
3、循环链表:链表的头指向链表的尾,一般用双向指针表示。
双向循环链表,链表的list->tail. next=list->head list->head.prev=list->tail 即头的上一个指向尾,尾的下一个指向头
约瑟夫环:每次第三个都删除,直到剩下最后一个
struct LinkStack
{
DLlist stack;
ElementType Topdata;
};
typedef struct LinkStack LStack;
int InitLinkStack(LStack *s)
{
return InitDLinkList(&s->stack);
}
struct Node *GetTop(LStack *s)
{
return s->stack.tail;
}
void Push(LStack *s,ElementType element)
{
InsertTail(&s->stack,element);
}
ElementType* Pop(LStack *s)
{
if(s->stack.tail==NULL)
{
return NULL;
}
s->Topdata=s->stack.tail->data;
RemoveByIndex(&s->stack,s->stack.len-1);
return &s->Topdata;
}
void FreeStack(LStack *s)
{
FreeDLinkList(&s->stack);
}
- 表达式解析:输入“1+2+3=”类似的表达式,输出结果
#include"LinkStack.h"
#include<stdio.h>
#include<stdlib.h>
#define true 1
#define false 0
int IsOper(char c)
{
switch(c)
{
case '+':
case '-':
case '*':
case '/':
case '=':
case '(':
case ')':
return true;
default:
return false;
}
}
int IsNum(char c)
{
if(c>='0'&&c<='9')
return true;
else
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)
{
printf("devide zero!\n");
exit(-1);
}
return prev/next;
default:
return false;
}
}
char Percede(char ch1,char ch2)
{
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;
}
char pre[7][7]=
{
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='}
};
return pre[i][j];
}
int main()
{
LStack Num;
InitLinkStack(&Num);
LStack Oper;
InitLinkStack(&Oper);
Push(&Oper,'=');
char str[100]={0};
scanf("%s",str);
int i=0;
while(str[i]!='\0')
{
if(IsOper(str[i]))
{
switch(Percede(GetTop(&Oper)->data,str[i]))
{
case '<':
Push(&Oper,str[i]);
i++;
break;
case '>':
int next=*Pop(&Num);
int prev=*Pop(&Num);
Push(&Num,Operate(prev,next,*Pop(&Oper)));
break;
case '=':
Pop(&Oper);
i++;
break;
default:
break;
}
}
else if(IsNum(str[i]))
{
int lower =str[i]-'0';
Push(&Num,lower);
i++;
while(IsNum(str[i]))
{
int num=str[i]-'0';
int higher=*Pop(&Num);
Push(&Num,(higher)*10+num);
i++;
}
}
else if(str[i]==' ')
{
while(str[i]==' ')
{
i++;
}
}
}
printf("the answer is %d \n",*Pop(&Num));
return 0;
}