370 likes | 524 Views
栈和队列. 进制转换. 77 10 =1001101 2. {} 的匹配检查. 一个 cpp 程序中有很多 {} ,那么都是否匹配的呢? 匹配原则:每个 { 与向后和它最近的那个 } 为匹配的一组 这样的匹配检查的算法是怎样的?. // 全组合的算法 for(j=1;j<k+1;j++) C[j]=j; Cout; i=k; while(i>0) { while(C[i]+k-i<n) {C[i]=C[i]+1; for(j=i+1;j<k+1;j++) C[j]=C[j-1]+1; Cout; i=k; }
E N D
进制转换 7710=10011012
{}的匹配检查 一个cpp程序中有很多{},那么都是否匹配的呢? 匹配原则:每个{与向后和它最近的那个}为匹配的一组 这样的匹配检查的算法是怎样的?
//全组合的算法 for(j=1;j<k+1;j++) C[j]=j; Cout; i=k; while(i>0) { while(C[i]+k-i<n) {C[i]=C[i]+1; for(j=i+1;j<k+1;j++) C[j]=C[j-1]+1; Cout; i=k; } i=i-1; }
//全组合的算法的list版本 list<int> C; C.push_back(1); while(C.size()<k) C.push_back(C.back()+1); Cout(C); while(!C.empty()) { while(C.back()+k-C.size()<n) { temp=C.back(); C.pop_back(); C.push_back(temp+1); while(C.size()<k) C.push_back(C.back()+1); Cout(C); } C.pop_back(); }
全排列的求解 • 全组合与全排列之间的差别? 1 2 3 4 1 2 4 3 1 3 2 4 1 3 4 2 .. .. .. 能否在全组合的算法上做点儿修改得到全排列的算法呢?
P.push_back(1); while(P.size()<n) P.push_back(P.back()+1); nonused.clear(); Cout(P); while(!P.empty() ){ for(i=nonused.begin() ;i!=nonused.end()&&(*i<P.back());i++); if(i!=nonused.end()){ temp=P.back(); P.back()=*i; nonused.erase(i); for(i=nonused.begin() ;i!=nonused.end()&&(*i<temp);i++); nonused.insert(i,temp);
while(!nonused.empty()){ P.push_back(nonused.front()); nonused.pop_front(); } Cout(P); } else{ nonused.push_back(P.back()); P.pop_back(); } }
八皇后的排列 满足一定条件的排列 根据问题的实际思路来排列
前面提到的几个问题的数据处理上,有什么共同点吗?前面提到的几个问题的数据处理上,有什么共同点吗?
栈 stack • 栈是一种特殊的线性表 • 栈限定在表尾进行插入和删除 • 数据先入后出(FILO, first in last out)
list和vector中的栈操作 push_front() 从头部插入 pop_front() 从头部删除 push_back() 从尾部插入 pop_back() 从尾部删除
使用栈操作的一个例子—括号匹配检查 #include <string> int check(string str)//返回在str字符串中第一个没有匹配括号的字符的位子 //例如 对 "{{}"返回 0, 对"{{}}{}}"返回6 { list<int> st; for(int i=0;i<str.length();i++) { if (str[i]=='{') st.push_back(i); else if (str[i]=='}' ) if(!st.empty()) st.pop_back(); else return i; } if (!st.empty()) return st.back(); }
函数调用的情况 g() { .. h(); .. } h() { .. l(); .. } f() { .. g(); .. }
何时需要使用栈? • 如果你在进行某种工作时,需要存储先前的工作状况,以便于在需要的时候回去修改,从而可以走另外不同的方向,则可以使用栈的思想 • 在逻辑上,对每个点采用同样的逻辑,且所作的修改都只与最后的一个节点有关
栈的使用注意事项 • 首先分析出需要使用栈的地方,理顺解决问题的思路 • 确定栈中应该存储的数据的结构
练习 现在要对一个方形的迷宫进行求解。回答下述问题: • 这个问题用栈的思想怎么解决? • 如果用栈的话,应该在栈中存储那些数据? • 存储的数据在栈中应如何表示?
栈的声明 class Stack { public: // constructors and destructor: Stack(); // default constructor Stack(const Stack& aStack); // copy constructor ~Stack(); // destructor // stack operations: bool isEmpty() const; void push(StackItemType newItem); void pop() ; StackItemType getTop( ) const; private: .. .. .. };
栈的连续存储方式 class Stack{ .. .. .. private: StackItemType *ps; // StackItemType ps[MAXNUM]; int ptop; };
ptop • 数据的存储采用(动态)数组 • 插入删除都通过移动ptop实现, ptop 为当前栈顶元素的下标, ptop取-1 表示栈为空, 所以初始化时ptop=-1
Stack::Stack() { ptop=-1; ps=NULL; }
void Stack::push(StackItemType data) { ptop++; ps[ptop]=data; } //如果使用的是动态数组, //此处应调整预先分配的空间的大小
void Stack::pop( ) { if (ptop>-1) ptop--; }
StackIteType Stack::gettop( ) { return ps[ptop]; }
bool Stack::isEmpty( ) { return ptop<=-1;//return top==-1; }
栈的链式存储 class Stack{ .. .. .. private: struct StackNode // a node in the stack { StackItemType data; // a item in the stack StackNode *next; // pointer to the next }; // end struct StackNode *topPtr; // pointer to first node };
topPtr 插入删除都在topPtr部分
void Stack::push(StackItemType data) { StackNode *newnode; newnode=new StackNode; newnode->data= data; newnode->link= topPtr; topPtr =newnode; } //初始状态下 topPtr =NULL
void Stack::pop( ) { StackNode *temp; if (topPtr!=NULL) { temp= topPtr; topPtr = topPtr ->link; deletetemp; } }
StackIteType Stack::gettop( ) { if (topPtr!=NULL) return topPtr ->data; }
bool Stack::isEmpty( ) { return topPtr ==NULL; }
stack模版 • 头文件 <stack> • 命名空间 std • 主要函数 push, pop, top, empty • 使用方式 #include <stack> using namespace std; stack<sometype> st; st.pop(), st.push(somedata), st.top().. .. ..
使用stack模版的一个例子 int check(string str)//返回在str字符串中第一个没有匹配括号的字符的位子 //例如 对 "{{}"返回 0, 对"{{}}{}}"返回6 { stack<int> st; for(int i=0;i<str.length();i++) { if (str[i]=='{') st.push(i); else if (str[i]=='}' ) if(!st.empty()) st.pop(); else return i; } if (!st.empty()) return st.top(); }
上机试验 • 写程序,实现可对迷宫的自动求解
队列 queue • 队列也是一种特殊的线性表 • 队列限定在一端进行插入,在另一端进行删除 • 数据先入先出(FIFO, first in first out)
list和vector中的队列操作 push_front() 从头部插入 pop_back() 从尾部删除 push_back() 从尾部插入 pop_front() 从头部删除
queue模版 • 头文件 <queue> • 命名空间 std • 主要函数 push, pop, front, back, empty • 使用方式 #include <queue> using namespace std; queue<sometype> qu; qu.pop(), qu.push(somedata), qu.front(), qu.back().. .. ..