大一数据结构基础考核

数据结构基础

1. 实现一个函数,参数为一个字符串,该字符串中只包含左花括号

{ 和右花括号 } ,如果左右括号是匹配的,那么函数返回 True,
否则返回 False

比如,这个字符串是匹配的:{{}}

还有这样:{}{{}}{}{{}{}}

但是这样的字符串是不匹配的:{}}}{{}{}{{}}}

利用数据结构的知识解题。

- 非常裸的一个栈题

- 把字符串a传入 rev函数中 ,遍历a中的所有元素,

    碰到左括号 就push,栈顶指针top++,
    
    碰到 右括号 尝试pop,如果当前栈定没有 左括号

    则pop失败,直接返回 0,如果成功pop,栈顶指针向下移动一位 top--

    最后判断top == 0 是否成立,如果字符串是完全匹配的,栈为空,top==0

    反之,top!=0 栈内还有元素
#include <bits/stdc++.h>
using namespace std;
const int N=5e5;
char a[N],b[N];
int top=0;
int rev(char *s){
	int len=strlen(s);
	for(int i=0;i<len;++i){
		if(s[i]=='{'){
			b[top++] = s[i];
		}
		else if(s[i]=='}'){
			if(b[top-1]=='{'){
				top--;
			}
			else return 0;
		}
	}
	if(top == 0) return 1;
	else return 0;
}
int main(){
	gets(a);
	if(rev(a)==1) printf("True\n");
	else printf("False\n");
	return 0;
}

2. 实现所给函数,完成单向链表的反转

(不允许开辟新的空间,不允许修改所给结构/类以及函数的定义)

注意:使用递归满分,其他视情况给分

- 思路是把链表的所有箭头都反向,指向他前一个
- 比如 1 -> 2 -> 3 -> 4 -> 5

    rev: 1 <- 2 <- 3 <- 4 <- 5

- 因为是单链表 只有i->next,所以需要储存当前节点 now 和上一个节点 pre

    正好用递归可以实现,node *now = rev(pre->next); 当前节点now是递归的末尾节点

    now->next = pre , 当前节点指向上一个节点

    pre的下一个节点设置成NULL,然后return pre ,作为上一个节点的now,继续递归,当前节点now为空

    因为这个算法只改变了箭头的指向,而没有改变head 和 end,

    所以遍历的时候,从end开始遍历。
if(now != NULL){
            now->next = pre;
            pre->next = NULL;
        }
#include <bits/stdc++.h>
using namespace std;
struct node{
    int data;
    node *next;
};
class li{
    node *head,*end;
public:
    li():head(NULL),end(NULL){}
    void push(int x){
        node *newnode = new node;
        newnode->data = x;
        newnode->next = NULL;
        if(head == NULL){
            head = newnode;
        }
        else {
            end->next = newnode;
        }
        end = newnode;
    }
    void print(){
        node *thead = head;
        while(thead!=NULL){
            cout<<thead->data<<" ";
            thead = thead->next;
        }
    }
    node *rev(node *pre){
        if(pre==NULL) return NULL;
        if(pre->next==NULL) return pre;
        node *now = rev(pre->next);
        if(now != NULL){
            now->next = pre;
            pre->next = NULL;
        }
        return pre;
    }
    void chang(){
        rev(head);
        node *tend = end;
        while(end!=NULL){
            cout<<end->data<<" ";
            end = end->next;
        }
    }
};
int main(){
    li A;
    int n,t;
    cin>>n;
    while(n--){
        cin>>t;
        A.push(t);
    }
    A.chang();
    return 0;
}

3. 使用栈实现队列的下列操作:

push(x) -- 将一个元素放入队列的尾部。

pop() -- 从队列首部移除元素。

peek() -- 返回队列首部的元素。

empty() -- 返回队列是否为空。

- 用两个栈来模拟队列
    
    push 就是入栈

    pop 移除队列首部的第一个元素
    
        因为stack是 后进先出,所以尝试把stack中的每一个元素中重新装入一个新的stack

        这样就把原来的栈中的元素,完全颠倒了位置,达到了队列的要求(先进先出)
    peek 同样使用pop中的方法实现
    
    empty 调用stack中的empty
#include <bits/stdc++.h>
using namespace std;
stack<int > s,q;
void push(int i){
    s.push(i);
}
bool empty(){
    if(s.empty()) return 1;
    else return 0;
}
void pop(){
    while(!s.empty()){
        q.push(s.top());
        s.pop();
    }
    int val = q.top();
    q.pop();
    while(!q.empty()){
        s.push(q.top());
        q.pop();
    }
}
int peek(){
    while(!s.empty()){
        q.push(s.top());
        s.pop();
    }
    int val = q.top();
    while(!q.empty()){
        s.push(q.top());
        q.pop();
    }
    return val;
}
int main(){
    int x;
    string ch;
    while(1){
        cin>>ch;
        if(ch=="push"){
            cin>>x;
            push(x);
        }
        if(ch=="pop"){
            pop();
        }
        if(ch=="exit") break;
        if(ch=="peek"){
            cout<<peek()<<endl;
        }
        if(ch=="empty"){
            cout<<empty()<<endl;
        }
    }
}

4. 实现所给函数,实现删除链表的倒数第 n 个节点,并且返回链表的头结点。

(不允许修改所给结构/类以及函数的定义)

比如:一个单链表为 1->2->3->4->5,输入 n = 3 后,

得到的答案应该
为:1->2->4->5
输入的 n 保证是合法有效的。

注意:使用一遍扫描实现满分,其余视情况给分

- 实现倒数第k个,相当于正数第n-k+1个,

    使用两个指针,都指向head,第一个指针先走k步,

    然后第二个指针再开始走,等第一个指针走到链表的尾部时,第二个指针停止的地方就是要删除的元素

    因为要删除它,所以应该让第二个指针指向 被删除元素的前一个元素,
    那么第一个指针就要多走一步。

    然后 thead->next = thead->next->next  就行了

    不过还要特判一下 删除倒数第n个元素,即正数第一个元素
    直接 让 head = head->next即可,就是把指针头移到第二个元素那么,当做头节点
#include <bits/stdc++.h>
using namespace std;
struct node{
    int data;
    node *next;
};
class li{
    node *end,*head;
public:
    li():end(NULL),head(NULL){}
    void push(int x){
        node *newnode = new node;
        newnode->data = x;
        newnode->next = NULL;
        if(head==NULL){
            head = newnode;
        }
        else {
            end->next = newnode;
        }
        end = newnode;
    }
    void print(){
        node *thead = head;
        while(thead!=NULL){
            cout<<thead->data<<" ";
            thead = thead->next;
        }
    }
    void updata(int i){
        node *p = head,*thead = head;
        while(i--&&p->next!=NULL) p = p->next;
        cout<<p->data<<endl;
        if(p->next==NULL) head = head->next;
        else{
            p = p->next;
            while(p!=NULL){
                thead = thead->next;
                p = p->next;
            }
            thead->next = thead->next->next;
        }
    }
};
int main(){
    li A;
    int t,n;
    cin>>n;
    for(int i=0;i<n;++i) {
        cin>>t;
        A.push(t);
    }
    A.print();
    cin>>t;
    cout<<endl;
    A.updata(t);
    A.print();
    return 0;
}

5. 实现一个函数,参数为两个整数a和b,且保证 a + b < 2147483647,

函数返回他们的和,即 a + b。
(WQH:真的以为这么简单?)

要求:不允许使用符号 + - * /

  • 用位运算实现 +

位运算实现加法

#include <bits/stdc++.h>
using namespace std;
int add(int a,int b){
    int ret = 0;
    while(b){
        ret = a^b;
        b = (a&b)<<1;
        a = ret;
    }
}
int main(){
    int a,b;
    cin>>a>>b;
    cout<<add(a,b);
    return 0;
}

posted @ 2019-03-14 20:08  南风--  阅读(307)  评论(0编辑  收藏  举报