这里是水水水的数据结构课的笔记
1.线性表:一些无脑的操作
低配vector,线性表无序有序都可以通过下标快速访问。
但是修改操作耗时大,建议不太灵活,多组读取的数据使用
#include <iostream>
using namespace std;
template <typename E>
class List{
private:
void operator = (const List&){}
List(const List&){}
public:
List(){};
virtual ~List(){}
virtual void clear()=0;
virtual void append(const E&);
virtual E remove()=0;
virtual void moveToStart()=0;
virtual void moveToEnd()=0;
virtual void pre()=0;
virtual void nxt()=0;
//带const的函数只能读取数据成员 不能修改
virtual int length()const=0;
virtual int currPos()const=0;
virtual void moveToPos(int pos)=0;
virtual const E& getVal() const=0;
protected:
};
template <typename E>
class AList {
private:
int maxSize;
int ListSize;
int curr;
E* ListArray;
public:
AList(int size = 0){
maxSize=size;
ListSize=curr=0;
ListArray = new E[maxSize];
}
~AList(){
delete [] ListArray;
}
void clear(){
delete [] ListArray;
AList();
}
void insert(const E& it){
for(int i=ListSize;i>curr;i--){
ListArray[i]=ListArray[i-1];
}
ListArray[curr]=it;
ListSize++;
}
void append(const E& it){
ListArray[++ListSize]=it;
}
E remove(){
E tmp=ListArray[curr];
for(int i=curr;i<ListSize;i++){
ListArray[i]=ListArray[i+1];
}
ListSize --;
return tmp;
}
void moveToStart(){
curr=0;
}
void moveToEnd(){
curr=ListSize;
}
int length()const{
return ListSize;
}
int curPos()const{
return curr;
}
void moveToPos(int pos){
curr=pos;
}
void nxt(){
if(curr!=ListSize) curr++;
}
void pre(){
if(curr!=0) curr--;
}
const E& getVal(){
return ListArray[curr];
}
void reverse(){
for(int i=0;i<=ListSize/2;i++){
swap(ListArray[i],ListArray[ListSize-i-1]);
}
}
void print(){
cout<<"The number of elements: "<<ListSize<<endl;
for(int i=0;i<ListSize;i++)
cout<<ListArray[i]<<" ";
cout<<endl;
}
protected:
};
2.链表
链表的插入删除较为简便,但是查找元素比较不划算
#include<iostream>
using namespace std;
//一个双向链表的节点内容,包括数据,pre,与nxt
template <typename E>
struct Link{
Link(const E& t){
data=t;
nxt=NULL;
pre=NULL;
}
E data;
Link<E> *nxt, *pre;
};
template <typename E>
class List{
public:
//构造函数
List(){
first=NULL;
last=NULL;
ListSize=0;
}
//复制构造函数
List(const List & L){
Link<E> *tmp, *src,*dup;
if(L.ListSize == 0){
List();
return ;
}
first=new Link<E>(L.first->data);
src=L.first;
dup=first;
while(src->nxt != NULL){
src=src->nxt;
dup->nxt=new Link<E> (src->data);
tmp=dup;
dup=dup->nxt;
dup->pre=tmp;
}
last=dup;
ListSize=L.ListSize;
}
//析构函数
~List(){
while(first!=NULL){
Link<E> *tmp=first->nxt;
delete first;
first=tmp;
}
}
///打印链表内容
void print(){
Link<E> *tmp=first;
for(int i=0;i<ListSize;i++){
cout<<tmp->data<<" ";
tmp=tmp->nxt;
}
return ;
}
//在末尾插入元素
void Push_back(E t){
Link<E> *tmp=new Link<E>(t);
if(ListSize==0){
last=first=tmp;
}
else{
last->nxt=tmp;
last=tmp;
}
ListSize++;
}
void Del(int pos);
//合并链表 建新链表
void Merge(List<E> &t){
List <E> c;
Link<E> *t1=first,*t2=t.first;
while(t1!=NULL && t2!=NULL){
if(t1->data<t2->data){
c.Push_back(t1->data);
t1=t1->nxt;
}
else{
c.Push_back(t2->data);
t2=t2->nxt;
}
}
while(t1!=NULL){
c.Push_back(t1->data);
t1=t1->nxt;
}
while(t2!=NULL){
c.Push_back(t2->data);
t2=t2->nxt;
}
c.print();
}
private:
protected:
Link<E> *first,*last;
int ListSize;
};
int main(){
List<int> a,b;
a.Push_back(5);
a.Push_back(15);
a.Push_back(87);
a.Push_back(105);
b.Push_back(3);
b.Push_back(5);
b.Push_back(68);
b.Push_back(175);
cout<<"A: ";
a.print();
cout<<endl<<"B: ";
b.print();
cout<<endl;
cout<<"After Merging: ";
a.Merge(b);
return 0;
}
*嘤 一个无用的链表倒置
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
template <typename E>
struct ListNode{
E val;
ListNode<E> *nxt;
};
template<typename E>
ListNode<E>* Reverse(ListNode<E> *pHead){
if(pHead==NULL){
return NULL;
}
//head无实际意义 head->nxt是第一个元素
ListNode<E> *pCur=pHead->nxt,*pPre=NULL,*pNxt;
while(pCur!=NULL){
//记录下一个 下次用
pNxt=pCur->nxt;
if(pNxt==NULL){
//如果cur是最后一个
//指向
pCur->nxt=pPre;
//把头标记一下,第一个即为当前的最后一个
pHead->nxt=pCur;
return pHead;
}
pCur->nxt=pPre;
//前一个更新
pPre=pCur;
//下一个更新 记录好啊
pCur=pNxt;
}
}
int main(){
//头节点 当前尾节点 临时节点
ListNode<int> *head=new ListNode<int>,*cur=head,*p;
head->nxt=cur;
//插入操作
for(int i=1;i<=5;i++){
p=new ListNode<int>;
p->val=i;
cur->nxt=p;
cur=p;
}
cur->nxt=NULL;
ListNode <int>*tmp=head->nxt;
while(tmp!=NULL){
cout<<tmp->val<<" ";
tmp=tmp->nxt;
}
cout<<endl;
cout<<"After reverse: ";
Reverse(head);
tmp=head->nxt;
while(tmp!=NULL){
cout<<tmp->val<<" ";
tmp=tmp->nxt;
}
cout<<endl;
return 0;
}
3.栈 - 手写大法好
先进后出(FILO)的数据结构,可以用来处理字符匹配的问题
#include<iostream>
#define ll long long
//计算fabi函数 用栈代替
using namespace std;
int n;
template < typename E>
class Stack{
public:
Stack(){
top=0;
}
int top;
E s[100000];
void Push(E x){
s[++top]=x;
}
E Pop(){
return s[top--];
}
E Top(){
return s[top];
}
private:
protected:
};
void work(){
ll last=1,cnt=0;
Stack<ll> s;
s.Push(0);
while(cnt<n){
ll save=s.Top();
ll now=save;
s.Pop();
now+=last;
last=save;
cnt++;
cout<<"f["<<cnt<<"]= "<<now<<endl;
s.Push(now);
}
}
int main(){
//n为计算总次数
scanf("%d",&n); work(); return 0;
}
4.队列
先进先出(FIFO)的数据结构,比栈多了个头,写起来蛮顺手的,不像链表…
#include<iostream>
using namespace std;
template <typename E>
class AQueue{
private:
int maxSize;
int front;
int rear;
E * listArray;
bool isEmpty;
int cnt;
public:
AQueue(int size=0){
maxSize=size+1;
rear=0;
front=1;
cnt=0;
listArray= new E[maxSize];
}
~AQueue(){
delete [] listArray;
}
void clear(){
rear=0;
front=1;
}
void add(const E& it){
listArray[++rear]=it;
cnt++;
}
E del(){
cnt--;
E it=listArray[front++];
return it;
}
const E& getFont()const{
return listArray[front];
}
virtual int length()const{
return rear-front+1;
}
void judge(){
if(cnt){
//isEmpty=0;
cout<<"The queue is not empty."<<endl;
}
else {
//isEmpty=1;
cout<<"The queue is empty."<<endl;
}
}
};
int main(){
//检测功能
AQueue<int> q(80);
for(int i=1;i<=7;i++) q.add(i);
cout<<"Delte these elements: ";
for(int i=1;i<=5;i++)cout<<q.del()<<" ";
cout<<endl;
q.judge();
cout<<"Delte these elements: ";
for(int i=1;i<=2;i++)cout<<q.del()<<" ";
cout<<endl;
q.judge();
return 0;
}