首页 > 试题广场 >

请设计一个排队系统,能够让每个进入队伍的用户都能看到自己在队

[问答题]
请设计一个排队系统,能够让每个进入队伍的用户都能看到自己在队列中所处的位置和变化,队伍可能随时有人加入和退出;当有人退出影响到用户的位置排名时需要及时反馈到用户
设计一个链式的队列,由于队列频繁的有人来和走(插入和删除),所以链式队列的效率最好,队列中存放的元素是一个对象和队长,这个对象包括了 Person、location属性,Person是排队的用户,而location是用户的位置,当有用户进来的时候,只能从队尾进入,此时将他的 Person对象加入,其location等于队长加1,并且队长加1;如果有用户退出(任何位置),找到退出的用户的前一个用户,删除退出用户的结点, 并且其后的其他用户的location-1,队长也-1.
为了更快的找到退出的用户,可以考虑用HashMap存储用户的key:Hash值,val:链表结点的位置。
发表于 2015-07-23 16:18:06 回复(2)
观察者模式
发表于 2015-01-19 00:30:28 回复(0)
这道题是给人吐槽用的么?
发表于 2014-09-23 22:57:04 回复(4)
#include<iostream>
#include<list>
#include<string>

using namespace std;

class clientQueue; //前向申明

class client{
public:
	client(string xname,size_t xpos =0):name(xname),pos(xpos){}
	
	void addIntoQueue(clientQueue &queue);
	void leaveFromQueue(clientQueue &queue);
	string name;
	size_t pos;

};

class clientQueue{
public:
	size_t  queueSize() { return clientList.size();}
	void    incClient(client * cli); //必须用指针,否则存放的是对象的拷贝
	void    decClient(client * cli) ;

private:
	list<client *> clientList;


};

void client::addIntoQueue(clientQueue &queue)
{
	queue.incClient(this);
}

void client::leaveFromQueue(clientQueue &queue)
{
	queue.decClient(this);
}


void clientQueue::incClient(client * cli)
{
	 clientList.push_back(cli); //将新客户加入队列末尾
	 cli->pos = clientList.size(); // 更新新客户位置

}

void clientQueue::decClient(client * cli)
{
	list<client *>::iterator it = clientList.begin();
		
	advance(it,cli->pos);  //找到要删除的位置的后面一个client,从其开始的所有client的位置
	for(;it !=clientList.end(); ++it )
		( (*it)->pos )--;	
	it = clientList.begin();
	advance(it,cli->pos-1); //删除该client
	clientList.erase(it);
	cli->pos =0; //将被删除的client的pos置为0

}
int main()
{
	client a("A"),b("B"),c("C"),d("D"),e("E"); //新建五个client  A B C D E

	clientQueue queue;

	a.addIntoQueue(queue);
	b.addIntoQueue(queue);
	c.addIntoQueue(queue);

	
	cout << a.pos <<" " << b.pos << " " <<c.pos << " " << d.pos << " " << e.pos << endl;
	
	b.leaveFromQueue(queue);
	cout << a.pos <<" " << b.pos << " " <<c.pos << " " << d.pos << " " << e.pos << endl;
	d.addIntoQueue(queue);
	e.addIntoQueue(queue);
	cout << a.pos <<" " << b.pos << " " <<c.pos << " " << d.pos << " " << e.pos << endl;

	a.leaveFromQueue(queue);
	cout << a.pos <<" " << b.pos << " " <<c.pos << " " << d.pos << " " << e.pos << endl;
}

发表于 2015-08-28 17:08:28 回复(0)
// 客户类
class Custom {
public:
    Custom(int s) {
        index = 0;
        serial = s;
        next = NULL;
        prev = NULL;
    }
    
    // 刷新排名信息
    void Refresh(){
        printf("排在号码为 %d 客户的前面还有 %d 人\n",serial,index);
    }
    
    // 位置向前移动
    void GoAhead(){
        --index;
        Refresh();
        if (NULL!=next) {
            next->GoAhead();
        }
    }
    
    // 位置向后移动
    void GoBack() {
        ++index;
        Refresh();
        if (NULL!=next) {
            next->GoBack();
        }
    }
    
    // 获取当前位置
    int GetIndex() {
        return index;
    }
    
    int index;
    int serial;
    Custom * next;
    Custom * prev;
};

// 排队系统
class QueuingSystem
{
public:
    QueuingSystem(){
        m_head = NULL;
        m_tail = NULL;
        num = 0;
    }
    
    // 添加排队客户,排到队尾
    void AddToBack(int s) {
        Custom * p = new Custom(s);
        if ( NULL==m_head ) {
            m_head = p;
            m_tail = m_head;
            
        }
        else {
            p->index = m_tail->index+1;
            m_tail->next = p;
            p->prev = m_tail;
            m_tail = p;
        }
        p->Refresh();
        ++num;
    }
    
    // 将 c 插队到 t 的前面
    bool InsertTo(Custom * c,Custom * t) {
        if ( NULL==c || NULL==t ) {
            return NULL;
        }
        
        c->next = t;
        if ( NULL!=t->prev ) {
            t->prev->next = c;
            c->prev = t->prev;
            c->index = t->prev->index+1;
        }
        else {
            m_head = c;
            c->index = 0;
        }
        t->prev = c;
        c->next->GoBack();
        ++num;
        return true;
    }
    
    // 添加排队客户,插队到流水号为 to 的前面
    bool InsertTo(int s,int to) {
        if ( NULL==m_head ) {
            return false;
        }
        
        Custom * p = m_head;
        while( NULL!=p ) {
            if (to==p->serial) {
                return InsertTo(new Custom(s),p);
            }
            p = p->next;
        }
        return false;
    }
    
    // 退出排队
    bool Quit(Custom * c) {
        if ( NULL==c ) {
            return false;
        }
        
        if ( NULL!=c->next ) {
            c->next->GoAhead();
        }
        if ( m_head==c ) {
            m_head = c->next;
        }
        if ( m_tail==c ) {
            m_tail = c->prev;
        }
        if ( NULL!=c->prev ) {
            c->prev->next = c->next;
        }
        if ( NULL!=c->next ) {
            c->next->prev = c->prev;
        }
        delete c;
        --num;
        return true;
    }
    
    // 退出排队
    bool Quit(int serial) {
        if ( NULL==m_head ) {
            return false;
        }
        Custom * p = m_head;
        while(NULL!=p) {
            if (serial==p->serial) {
                return Quit(p);
            }
            p = p->next;
        }
        return false;
    }
    
    // 叫号,排在队首的出列办理业务
    bool Pop(int & serial) {
        if ( NULL==m_head ) {
            return false;
        }
        else {
            serial = m_head->serial;
            return Quit(m_head);
        }
    }
    
    Custom * m_head;
    Custom * m_tail;
    int num;
};

编辑于 2015-05-16 00:32:00 回复(0)
#include <iostream> 
#include <list> 
#include <string> 
using namespace std;  
class User  
{  
private:  
    int id;  //唯一标识一个用户  
    string name;  
    int seq;  
public:  
    User(int id, string name, int seq = 0)  
    {  
        this->id = id;  
        this->name = name;  
        this->seq = 0;  
    }  
    string getName()  
    {  
        return name;  
    }  
    void setName(string name)  
    {  
        this->name = name;  
    }  
    int getSeq()  
    {  
        return seq;  
    }  
    void setSeq(int seq)  
    {  
        this->seq = seq;  
    }  
   int getId()  
    {  
        return id;  
    }  
    bool operator==(const User &u1)const  
    {  
        return (id == u1.id);  
    }  
};  
class MyQueue  
{  
private:  
    list<User> userList;  
public:  
    //进入队列尾部  
    void enQueue(User u)  
    {  
        u.setSeq(userList.size() + 1);  
        userList.push_back(u);  
    }  
    //队头出队列  
    void deQueue()  
    {  
        userList.pop_front();  
        updateSeq();  
    }  
    //队列中的人随机离开  
    void deQueue(User& u)  
    {  
        userList.remove(u);  
        updateSeq();  
    }  
    //出队列后更新队列中每个人的序列  
    void updateSeq()  
    {  
        int i = 1;  
        list<User>::iterator iter;  
        for (iter = userList.begin(); iter != userList.end(); ++iter)  
        {  
            iter->setSeq(i);  
            i++;  
        }  
    }  
    //打印队列的信息  
    void printList()  
    {  
        list<User>::iterator iter;  
        for (iter = userList.begin(); iter != userList.end(); ++iter)  
            cout << "id:" << iter->getId() << "  name:" << iter->getName() << "  seq:" << iter->getSeq() << endl;  
    }  
};  
int main()  
{  
    User u1(1, "user1");  
    User u2(2, "user2");  
    User u3(3, "user3");  
    User u4(4, "user4");  
    MyQueue queue;  
    queue.enQueue(u1);  
    queue.enQueue(u2);  
    queue.enQueue(u3);  
    queue.enQueue(u4);  
    queue.deQueue();  //对首元素u1出队列  
    queue.deQueue(u3); //队列中间的元素u3出队列  
    queue.printList();  
    return 0;  
} 

发表于 2018-06-06 11:26:26 回复(0)
观察者模式
发表于 2015-04-17 16:30:41 回复(0)
@Data
public void QueueSys {

    private Person head;

    private Person tail;

    private int size;

    private Object lock;

    public QueueSys() {
        size = 0;
        head = null;
        tail = null;
    }

    // 入队
    public int enQueue(Person p) {
        if (p.flag) return -1;
        synchronized (lock) {
            if (tail != null) {
                tail.next = p;
                tail = tail.next;
            }else {
                tail = p;
                head = p;
            }
            p.flag = true;
            return ++size;
        }
    }

    // 离队
    public void deQueue(Person p) {
        synchronized (lock) {
            int pos = 1;
            Person cur = head, pre = null;
            while(cur != null && cur != p) {
                pre = cur;
                cur = cur.next;
                ++pos;
            }
            // 移除cur
            cur.leave();
            pre.next = cur.next;
            // 通知cur后面元素
            cur = cur.next;
            int offset = 0;
            while(cur != null) {
                // 通知位置变更
                cur.handleMoveMsg(pos + offset);
            }
            p.next = null;
            p.flag = false;
        }
    }
}

class Person {
    public int position;

    public Person next;

    // 是否入队
    public boolean flag;

    private QueueSys qs;

    public Person(QueueSysueu qs) {
        this.qs = qs;
        this.position = -1;
        this.next = null;
        this.flag = false;
    }

    public void handleMoveMsg(int curPos) {
        this.position = curPos;
        System.out.println("您现在的位置是: " + curPos);
    }

    public void leave() {
        qs.leave();
    }

    public void join() {
        int curPos = qs.enQueue(this);
        this.position = curPos;
    }
}
编辑于 2024-03-18 14:18:37 回复(0)
#include <iostream>
using namespace std;


struct User{
    int userID;
    int pos;
    User* nextUser;
    User(int _userId, int _pos): userID(_userId), pos(_pos), nextUser(nullptr) {}
};

class myQueue{
public:
    myQueue(){
        dummyHead=new User(-1,0);
        lastNode=dummyHead;
        length=0;
    }
    ~myQueue(){
        delete dummyHead;
        dummyHead=nullptr;
        lastNode=nullptr;
        length=0;
    }

    void addUser(int id){
        cout<<"addUser: \t";
        User* newUser=new User(id, ++length);
        lastNode->nextUser=newUser;
        lastNode=newUser;
        cout<<"The user "<<id<<" is added, its position is "<<newUser->pos<<"."<<endl;
    }

    void checkUser(int id){
        cout<<"checkUser: \t";
        if(length==0){
            cout<<"No user in queue."<<endl;
            return;
        }
        User* node=dummyHead->nextUser;
        while(node){
            if(node->userID==id){
                cout<<"User found in pos "<<node->pos<<"."<<endl;
                return;
            }
            node=node->nextUser;
        }
        cout<<"User not found."<<endl;
    }

    void deleteUser(int id){
        cout<<"deleteUser: \t";
        if(length==0){
            cout<<"Cannot delete, no user in queue."<<endl;
            return;
        }
        User* node=dummyHead->nextUser;
        User* preNode=dummyHead;
        while(node){
            if(node->userID==id){
                if(node==lastNode){
                    delete node;
                    preNode->nextUser=nullptr;
                    lastNode=preNode;
                    cout<<"The last user leaves, no one's position is changed."<<endl;
                }
                else{
                    preNode->nextUser=node->nextUser;
                    delete node;
                    cout<<"The user "<<id<<" leaves."<<endl;
                    node=preNode->nextUser;
                    cout<<"Pos Update: ";
                    while(node){
                        node->pos--;
                        cout<<"\tThe user "<<node->userID<<"'s new position is "<<node->pos<<"."<<endl;
                        node=node->nextUser;
                    }
                    
                }
                return;
            }

            node=node->nextUser;
            preNode=preNode->nextUser;
        }

        cout<<"The user id is not found."<<endl;
    }
private:
    User* dummyHead;
    User* lastNode;
    int length;
};

int main(){
    myQueue queue;
    queue.addUser(1);
    queue.addUser(2);
    queue.addUser(4);
    queue.checkUser(1);
    queue.checkUser(3);
    queue.deleteUser(3);
    queue.deleteUser(1);
    queue.deleteUser(4);
    queue.deleteUser(2);

    return 0;
}

发表于 2020-04-26 16:30:00 回复(0)
1.链表
2.添加元素从队尾添加
3.每个元素都有index自己的位置
4.每个元素都监控前一个元素的变化,如果前一个元素删除则当前元素index--;
5.如果当前元素index--,后续元素监听并也执行--
发表于 2016-09-24 20:39:57 回复(0)
红黑树,结点维护子树结点个数
发表于 2016-04-02 16:02:47 回复(0)
<div> class user { </div> <div> public: </div> <div> <span> </span>string name; </div> <div> <span> </span>int num; </div> <div> <span> </span>int total; </div> <div> <span> </span>user(string s, int num, int total){this-&gt;name = s;this-&gt;num = num; this-&gt;total = total;} </div> <div> <span> </span>user(){name = ""; num = -1; total = -1;} </div> <div> }; </div> <div> <br /> </div> <div> class Mydeque{ </div> <div> <br /> </div> <div> public: </div> <div> <span> </span>deque&lt;user&gt; user_deq; </div> <div> <span> </span>static int length; </div> <div> <br /> </div> <div> <span> </span>void push_back(user u){ </div> <div> <span> </span>length++; </div> <div> <span> </span>deque&lt;user&gt;::iterator it; </div> <div> <span> </span>for (it = user_deq.begin(); it != user_deq.end(); it++) </div> <div> <span> </span>{ </div> <div> <span> </span>it-&gt;total = length; </div> <div> <span> </span>} </div> <div> <span> </span> </div> <div> <span> </span>u.num = length; </div> <div> <span> </span>u.total = length; </div> <div> <span> </span>user_deq.push_back(u); </div> <div> <span> </span> </div> <div> <span> </span>} </div> <div> <span> </span>user front(){ </div> <div> <span> </span>user temp = user_deq.front(); </div> <div> <span> </span>return temp; </div> <div> <span> </span>} </div> <div> <span> </span>void pop_front(){ </div> <div> <span> </span>length--; </div> <div> <span> </span>deque&lt;user&gt;::iterator it; </div> <div> <span> </span>user temp = user_deq.front(); </div> <div> <span> </span>user_deq.pop_front(); </div> <div> <span> </span>for (it = user_deq.begin(); it != user_deq.end(); it++) </div> <div> <span> </span>{ </div> <div> <span> </span>it-&gt;num -= 1; </div> <div> <span> </span>it-&gt;total = length; </div> <div> <br /> </div> <div> <span> </span>} </div> <div> <span> </span>} </div> <div> <br /> </div> <div> <span> </span>user find(string name){ </div> <div> <span> </span>deque&lt;user&gt;::iterator it; </div> <div> <span> </span>user temp; </div> <div> <span> </span>for (it = user_deq.begin(); it != user_deq.end(); it++) </div> <div> <span> </span>{ </div> <div> <span> </span>if (it-&gt;name == name){ </div> <div> <span> </span>temp = *it; </div> <div> <span> </span>break; </div> <div> <span> </span>} </div> <div> <span> </span>} </div> <div> <span> </span>if(it == user_deq.end()) </div> <div> <span> </span>throw exception("There is not such a man !"); </div> <div> <span> </span>else </div> <div> <span> </span>for (;it != user_deq.end(); it++) </div> <div> <span> </span>{ </div> <div> <span> </span>it-&gt;num -= 1; </div> <div> <span> </span>it-&gt;total -= 1; </div> <div> <span> </span>} </div> <div> <span> </span>return temp; </div> <div> <span> </span>} </div>
发表于 2015-09-04 22:37:21 回复(0)
<div> 原理:设定初始人数为menber=0,每次有人员变化时,修改人员个数,若退出,则退出位置之前的人位置不变,退出位置之后的人的位置减一 </div> <div> 若增加人,加入位置之前的人位置不变,位置之后人位置加一 </div>
发表于 2015-09-03 22:01:26 回复(0)
<div> 退出可在队伍的任何位置; </div> <div> 加入只能在队伍的末尾; </div> <div> 用链表来实现,可设置一个尾指针来进行加入操作,头指针用来执行退出和查看位置; </div>
发表于 2015-09-03 10:44:06 回复(0)
大体思路可以如下,具体函数就不一一实现了

//排队系统
class System{		

private:
	list<User> container;		//实际内部所用容器
	
public:
	addUser( User型变量 );		//仅在尾部添加用户
	deleteUser( User型变量 );	//可在任意位置移除用户,每delete一个User,就要updateUser一下以确保各个User的位置的及时更新
	printAllUser();				//遍历容器打印出所有用户的信息

private:
	updateAllUser();			//在里面遍历容器来重新设定序号
	
};

//用户
class User{

private:
	string name;	//姓名
	int rank;		//当前位置

public:
	User();			//ctor
	
public:
	getName();
	getRank();
	
public:
	setRank();
};

发表于 2015-08-30 15:46:11 回复(0)
<pre class="prettyprint lang-cpp">class Client{ public: Client *prev; Client *next; &nbsp; int id; &nbsp; int position; &nbsp; int getposition(){ return position; } void setposition(int p){ p=position; } void leavequeue(){ MyQueue::getInstance.remove(this); } void moveforward(){ position--; } friend MyQueue; } class MyQueue{ private: MyQueue{ } public: Static MyQueue* getInstance(){ if(myqueue==NULL){ head=new Client(); myqueue=new MyQueue(); } else return myqueue; }; int makeClientnum(){ id+=((1+id)%100000); return id++; } void removeNode(Client * client){ Client *next=client-&gt;next; Client *prev=client-&gt;prev; if(next==NULL){ } else { next-&gt;prev=prev; prev-&gt;next=next; while(next!=NULL){ next-&gt;moveforward(); size--; } } } Static int size=0; Static Client* head; Static MyQueue* myqueue; Static int id=0; Static unorderded_map&lt;int,Client *&gt; m; }</pre> <br />
发表于 2015-08-28 21:28:50 回复(0)
<div> 可以通过单向链表来实现。链表的结构包含一个值域(用于保存当前的位置)和一个指向下一个用户的指针。 </div> <div> 链表的插入代表有新用户加入队列,如果不允许插队,这时插入的应该放在链表的尾部,此时只需要将插入的部分的值域设置为其前驱加1. </div> <div> 队伍有人退出可以用链表的删除节点表示,将要退出的节点的下一节点的内容拷贝到要删除的节点然后删除下一节点并将此节点以后的所有节点的值域减1. </div>
发表于 2015-08-28 10:43:33 回复(0)
/*
1)建立队列=》入队,出队,出队的位置;
2)建立用户=》出队,入队,位置;
*/
#include<iostream>
#include<vector>
#include<list>
using namespace std;
class QueueUp
{
private:
	vector<int>m_vector;
public:
	QueueUp(bool m_exit,vector<int>& m_vector)
	{
		this->m_exit=false;
		this->m_dequeuePos=0;
		this->m_vector=m_vector;
	}
    QueueUp(vector<int>& m_vector)
	{
		this->m_exit=false;
		this->m_dequeuePos=0;
		this->m_vector=m_vector;
	}
	int EnQueue(int UserID)
	{
		m_vector.push_back(UserID);
        int len=m_vector.size();
		return len;
	}
	void DeQUeue(int postion)
	{
		m_vector.erase(m_vector.begin()+postion-1);
		this->m_exit=true;
		m_dequeuePos=postion;
	}
	bool m_exit;
	int m_dequeuePos;
	virtual ~QueueUp()
	{
		//cout<<"队列销毁!"<<endl;
	}	
};
class User
{
private:
	int m_Position;
	int m_UserID;
	QueueUp*m_Queue;
public:
	User(QueueUp*m_Queue,int m_UserID)
	{
		this->m_Queue=m_Queue;
		this->m_UserID=m_UserID;
	}
	User(){}
	void EnQuene()
	{	
		this->m_Position=this->m_Queue->EnQueue(this->m_UserID);
	}
	void DeQueue()
	{
		this->m_Queue->DeQUeue(this->m_Position);
	}
	int GetUserID()
	{
		return m_UserID;
	}
	int GetCurrentPos()
	{
		return this->m_Position;
	}
	void SetCurrentPos(int m_pos)
	{
		this->m_Position=m_pos;
	}
	virtual ~User()
	{
	//	cout<<"用户销毁!"<<endl;
	}
};


bool IsExit(QueueUp &m_Queue,list<User>& pUser)
{
	bool flag=false;
	if(m_Queue.m_exit)
	{
		cout<<m_Queue.m_dequeuePos<<"位置EXIT"<<endl;
		list<User>::iterator mIt;
		mIt=pUser.begin();
		int j=m_Queue.m_dequeuePos-1;
		while(j>0){mIt++;j--;}
		mIt=pUser.erase(mIt);
		while(mIt!=pUser.end())
		{
			User & m_user2=*mIt;
			m_user2.SetCurrentPos(m_user2.GetCurrentPos()-1);
			mIt++;
		}
        flag=true;
	}
	return flag;
}

void Test()
{
	vector<int>m_vector;
	QueueUp m_Queue(m_vector);
	list<User>pUser;
	list<User>::iterator mIt;
	int i=0;
	for(;i<10;i++)
	{
		User mUser(&m_Queue,100+i);
		mUser.EnQuene();
		pUser.push_back(mUser);
	}
    mIt=pUser.begin();
	while(mIt!=pUser.end())
	{
		cout<<(*mIt).GetUserID()<<"位置:"<<(*mIt).GetCurrentPos()<<endl;
		mIt++;
	}
	//出队
	char ch='n';
	while(ch!='y')
	{
    cout<<"出队的位置:";
	int m;
	cin>>m;
	cout<<endl;
	m_Queue.DeQUeue(m);
   if(IsExit(m_Queue,pUser))
   {
    mIt=pUser.begin();
	while(mIt!=pUser.end())
	{
		cout<<(*mIt).GetUserID()<<"位置:"<<(*mIt).GetCurrentPos()<<endl;
		mIt++;
	}
   }
   
   cout<<"是否结束(y=yes,n=no):";
   cin>>ch;
   cout<<endl;
	}
}

int main()
{
    Test();
	return 0;
}

发表于 2015-08-26 22:34:20 回复(0)
设计一个链表队列,反馈函数;
当有人加入的时候,就将其加入到链表的尾端,当有人退出的时候就将其从链表中去除(链表的增删是很好操作的),此时链表的结构将发生变化,即利用反馈函数通知用户。

发表于 2015-04-13 20:06:57 回复(0)
排队系统为链表结构。
节点结构为
struct   Node
{
int id;
int place;
int change; //上升为正,下降为负
Node *next;
};

每次加入新的节点,在末尾添加。
有节点退出,找到此节点,然后删除,后面的节点,place+1,change =1
发表于 2015-04-08 14:10:11 回复(0)