数据结构OJ实验2-链表

31 篇文章 12 订阅
16 篇文章 0 订阅

A. DS单链表--存储结构与操作

题目描述

实现含头结点的单链表

属性包括:data数据域、next指针域

操作包括:插入、删除、查找

注意:单链表不是数组,所以位置从1开始对应首结点,头结点不放数据

输入

第1行先输入n表示有n个数据,接着输入n个数据

第2行输入要插入的位置和新数据

第3行输入要插入的位置和新数据

第4行输入要删除的位置

第5行输入要删除的位置

第6行输入要查找的位置

第7行输入要查找的位置

输出

数据之间用空格隔开,

第1行输出创建后的单链表的数据

每成功执行一次操作(插入或删除),输出执行后的单链表数据

每成功执行一次查找,输出查找到的数据

如果执行操作失败(包括插入、删除、查找等失败),输出字符串error,不必输出单链表

样例查看模式 

正常显示查看格式

输入样例1

6 11 22 33 44 55 66
3 777
1 888
1
11
0
5

输出样例1

11 22 33 44 55 66 
11 22 777 33 44 55 66 
888 11 22 777 33 44 55 66 
11 22 777 33 44 55 66 
error
error
44

AC代码

#include<iostream>
using namespace std;
struct node 
{
	int data;
	node* next;
	node()
	{
		data = 0;
		next = NULL;
	}
};
class linklist
{
	node* root;
	int n;
public:
	linklist()
	{
		cin >> n;
		//注意root初始!
		root = new node;
		node* t = root;
		for (int i = 1; i <= n; i++)
		{
			int x;
			cin >> x;
			node* p = new node;
			p->data = x;
			t->next = p;
			t = p;//注意向后!
		}
		display();
	}
	void Insert(int idx, int d)
	{
		if (idx<1 || idx>n + 1)
		{
			cout << "error" << endl;
			return;
		}
		//idx从1开始
		node* q = new node;
		q = root;
		node* t = new node;
		t->data = d;
		for (int i = 1; i <idx; i++)
		{
			q = q->next;
		}
		t->next = q->next;
		q->next = t;//不用把t删除了!
		n++;
		display();
	}
	void Delete(int idx)
	{
		if (idx<1 || idx>n)
		{
			cout << "error" << endl;
			return;
		}
		node* q = new node;
		q = root;
		for (int i = 1; i < idx; i++)
		{
			q = q->next;
		}
		node* t = new node;
		t = q->next;
		q->next = t->next;
		delete t;
		n--;
		display();
	}
	void Find(int idx)
	{
		if (idx<1 || idx>n)
		{
			cout << "error" << endl;
			return;
		}
		node* q = new node;
		q = root;
		for (int i = 1; i <= idx; i++)
		{
			q = q->next;
		}
		cout << q->data << endl;
	}
	void display()
	{
		node* q = new node;
		q = root;
		for (int i = 1; i <= n; i++)
		{
			q = q->next;
			cout << q->data << " ";
		}
		cout << endl;
	}
};
int main()
{
	linklist l;
	for (int i = 0; i < 2; i++)
	{
		int x, y;
		cin >> x >> y;
		l.Insert(x, y);
	}
	for (int i = 0; i < 2; i++)
	{
		int x;
		cin >> x;
		l.Delete(x);
	}
	for (int i = 0; i < 2; i++)
	{
		int x;
		cin >> x;
		l.Find(x);
	}
	return 0;
}

B. DS单链表--结点交换

题目描述

用C++实现含头结点的单链表,然后实现单链表的两个结点交换位置。

注意不能简单交换两个结点包含数据,必须通过修改指针来实现两个结点的位置交换

交换函数定义可以参考:

swapNode(int  pa, int pb)  //pa和pb表示两个结点在单链表的位置序号

swapNode (ListNode * p, ListNode * q)  //p和q表示指向两个结点的指针

输入

第1行先输入n表示有n个数据,接着输入n个数据

第2行输入要交换的两个结点位置

第3行输入要交换的两个结点位置

输出

第一行输出单链表创建后的所有数据,数据之间用空格隔开

第二行输出执行第1次交换操作后的单链表数据,数据之间用空格隔开

第三行输出执行第2次交换操作后的单链表数据,数据之间用空格隔开

如果发现输入位置不合法,输出字符串error,不必输出单链表

样例查看模式 

正常显示查看格式

输入样例1 

5 11 22 33 44 55
1 4
2 6

输出样例1

11 22 33 44 55 
44 22 33 11 55 
error

AC代码

#include<iostream>
using namespace std;
struct node 
{
	int data;
	node* next;
	node()
	{
		data = 0;
		next = NULL;
	}
};
class linklist
{
	node* root;
	int n;
public:
	linklist()
	{
		cin >> n;
		//注意root初始!
		root = new node;
		node* t = root;
		for (int i = 1; i <= n; i++)
		{
			int x;
			cin >> x;
			node* p = new node;
			p->data = x;
			t->next = p;
			t = p;//注意向后!
		}
		display();
	}
	void Insert(int idx, int d)
	{
		if (idx<1 || idx>n + 1)
		{
			cout << "error" << endl;
			return;
		}
		//idx从1开始
		node* q = new node;
		q = root;
		node* t = new node;
		t->data = d;
		for (int i = 1; i < idx; i++)
		{
			q = q->next;
		}
		t->next = q->next;
		q->next = t;//不用把t删除了!
		n++;
		display();
	}
	void Delete(int idx)
	{
		if (idx<1 || idx>n)
		{
			cout << "error" << endl;
			return;
		}
		node* q = new node;
		q = root;
		for (int i = 1; i < idx; i++)
		{
			q = q->next;
		}
		node* t = new node;
		t = q->next;
		q->next = t->next;
		delete t;
		n--;
		display();
	}
	int Find(int idx)
	{
		if (idx<1 || idx>n)
		{
			cout << "error" << endl;
			return -1;
		}
		node* q = new node;
		q = root;
		for (int i = 1; i <= idx; i++)
		{
			q = q->next;
		}
		return q->data;
	}
	void display()
	{
		node* q = new node;
		q = root;
		for (int i = 1; i <= n; i++)
		{
			q = q->next;
			cout << q->data << " ";
		}
		cout << endl;
	}
	void Swap(int x, int y)
	{
		if (x<1 || x>n || y < 1 || y>n)
		{
			cout << "error" << endl;
			return;
		}
		//确保x<=y;
		if (x > y)swap(x, y);
		node* a = new node;
		a->data = Find(x);
		node* b = new node;
		b->data = Find(y);
		node* q = new node;
		q = root;
		for (int i = 1; i <= n; i++)
		{
			if (i==1&&x==1)
			{
				b->next = q->next->next;
				q->next = b;
				q = q->next;
				continue;
			}
			q = q->next;
			if (i == x-1)
			{
				b->next = q->next->next;
				q->next = b;
			}
			if (i == y - 1)
			{
				a->next = q->next->next;
				q->next = a;
				break;
			}
		}
		display();
	}
};
int main()
{
	linklist l;
	for (int i = 0; i < 2; i++)
	{
		int x, y;
		cin >> x >> y;
		l.Swap(x, y);
	}
	return 0;
}

C. DS单链表--合并

题目描述

假定两个单链表是递增有序,定义并实现以下函数,完成两个单链表的合并,继续保持递增有序

int LL_merge(ListNode *La, ListNode *Lb)

输入

第1行先输入n表示有n个数据,接着输入n个数据

第2行先输入m表示有M个数据,接着输入m个数据

输出

输出合并后的单链表数据,数据之间用空格隔开

样例查看模式 

正常显示查看格式

输入样例1 

3 11 33 55
4 22 44 66 88

输出样例1

11 22 33 44 55 66 88 

AC代码

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct node 
{
	int data;
	node* next;
	node()
	{
		data = 0;
		next = NULL;
	}
};
class linklist
{
	node* root;
	int n;
public:
	linklist()
	{
		cin >> n;
		//注意root初始!
		root = new node;
		node* t = root;
		for (int i = 1; i <= n; i++)
		{
			int x;
			cin >> x;
			node* p = new node;
			p->data = x;
			t->next = p;
			t = p;//注意向后!
		}
	}
	void Insert(int idx, int d)
	{
		if (idx<1 || idx>n + 1)
		{
			cout << "error" << endl;
			return;
		}
		//idx从1开始
		node* q = new node;
		q = root;
		node* t = new node;
		t->data = d;
		for (int i = 1; i < idx; i++)
		{
			q = q->next;
		}
		t->next = q->next;
		q->next = t;//不用把t删除了!
		n++;
		display();
	}
	void Delete(int idx)
	{
		if (idx<1 || idx>n)
		{
			cout << "error" << endl;
			return;
		}
		node* q = new node;
		q = root;
		for (int i = 1; i < idx; i++)
		{
			q = q->next;
		}
		node* t = new node;
		t = q->next;
		q->next = t->next;
		delete t;
		n--;
		display();
	}
	int Find(int idx)
	{
		if (idx<1 || idx>n)
		{
			cout << "error" << endl;
			return -1;
		}
		node* q = new node;
		q = root;
		for (int i = 1; i <= idx; i++)
		{
			q = q->next;
		}
		return q->data;
	}
	void display()
	{
		node* q = new node;
		q = root;
		for (int i = 1; i <= n; i++)
		{
			q = q->next;
			cout << q->data << " ";
		}
		cout << endl;
	}
	void Swap(int x, int y)
	{
		if (x<1 || x>n || y < 1 || y>n)
		{
			cout << "error" << endl;
			return;
		}
		//确保x<=y;
		if (x > y)swap(x, y);
		node* a = new node;
		a->data = Find(x);
		node* b = new node;
		b->data = Find(y);
		node* q = new node;
		q = root;
		for (int i = 1; i <= n; i++)
		{
			if (i==1&&x==1)
			{
				b->next = q->next->next;
				q->next = b;
				q = q->next;
				continue;
			}
			q = q->next;
			if (i == x-1)
			{
				b->next = q->next->next;
				q->next = b;
			}
			if (i == y - 1)
			{
				a->next = q->next->next;
				q->next = a;
				break;
			}
		}
		display();
	}
	friend void ll_merge(linklist x, linklist y)
	{
		node* xr = x.root;
		node* yr = y.root;
		vector<int>mm;
		xr = xr->next;
		while (xr)
		{
			mm.push_back(xr->data);
			xr = xr->next;
		}
		yr = yr->next;
		while (yr)
		{
			mm.push_back(yr->data);
			yr = yr->next;
		}
		sort(mm.begin(), mm.end());
		for (int i = 0; i < mm.size(); i++)
		{
			cout << mm[i] << " ";
		}
		cout << endl;
	}
};
int main()
{
	linklist x;
	linklist y;
	ll_merge(x, y);
	return 0;
}

D. DS循环链表—约瑟夫环(Ver. I - A)

题目描述

N个人坐成一个圆环(编号为1 - N),从第S个人开始报数,数到K的人出列,后面的人重新从1开始报数。问最后剩下的人的编号。

例如:N = 3,K = 2,S = 1。2号先出列,然后是1号,最后剩下的是3号。

要求使用循环链表实现。

输入

测试数据有多组

每组包括3个数N、K、S,表示有N个人,从第S个人开始,数到K出列。(2 <= N <= 10^6,1 <= K <= 10,  1 <= S <= N)

输出

出列的人的编号

样例查看模式 

正常显示查看格式

输入样例1 

13 3 1
3 2 1

输出样例1

3 6 9 12 2 7 11 4 10 5 1 8 13 
2 1 3 

AC代码

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct node
{
	int data;
	node* next;
	node* pre;
	node()
	{
		data = 0;
		next = NULL;
		pre = NULL;
	}
};
class circlelist
{
	node* root;
	int n, k, s;
public:
	circlelist(int nn, int kk, int ss)
	{
		n = nn;
		k = kk;
		s = ss;
		//注意root初始!
		root = new node;
		root->next = root;
		root->pre = root;
		for (int i = n; i>=1;i--)
		{
			node* p = new node;
			p->data = i;
			p->next = root->next;
			root->next->pre = p;
			root->next = p;
			p->pre = root;
		}
		root=root->next;
		Delete(root->pre);
		n++;//加入虚头结点
	}
	void Delete(node* d)
	{
		d->pre->next = d->next;
		d->next->pre = d->pre;
		delete d;
		n--;
	}
	node* Find(int idx)
	{
		node* q = root->next;
		if (root->data == idx)
		{
			return root;
		}
		while (q != root)
		{
			if (q->data == idx)return q;
			q = q->next;
		}
		return NULL;
	}
	void game()
	{
		node* q = Find(s);
		int count = 0;//记录到k
		while (q != q->next)
		{
			count++;
			q = q->next;
			if (count == k)
			{
				count = 0;
				cout << q->pre->data << " ";
				Delete(q->pre);
			}
		}
		cout << q->data << " " << endl;
	}
};
int main()
{
	int n, k, s;
	while (cin >> n >> k >> s)
	{
		circlelist c(n, k, s);
		c.game();
	}
	return 0;
}

E. DS线性表—多项式相加

题目描述

对于一元多项式p(x)=p0+p1x+p2x2+…+pnxn,每个项都有系数和指数两部分,例如p2x2的系数为p2,指数为2。

编程实现两个多项式的相加。

例如5+x+2x2+3x3,-5-x+6x2+4x4,两者相加结果:8x2+3x3+4x4

其中系数5和-5都是x的0次方的系数,相加后为0,所以不显示。x的1次方同理不显示。

要求用单链表实现。

输入

第1行:输入t表示有t组测试数据

第2行:输入n表示有第1组的第1个多项式包含n个项

第3行:输入第一项的系数和指数,以此类推输入n行

接着输入m表示第1组的第2个多项式包含m项

同理输入第2个多项式的m个项的系数和指数

参考上面输入第2组数据,以此类推输入t组

假设所有数据都是整数

输出

对于每1组数据,先用两行输出两个原来的多项式,再用一行输出运算结果,不必考虑结果全为0的情况

输出格式参考样本数据,格式要求包括:

1.如果指数或系数是负数,用小括号括起来。

2.如果系数为0,则该项不用输出。

3.如果指数不为0,则用符号^表示,例如x的3次方,表示为x^3。

4.多项式的每个项之间用符号+连接,每个+两边加1个空格隔开。

样例查看模式 

正常显示查看格式

输入样例1 

2
4
5 0
1 1
2 2
3 3
4
-5 0
-1 1
6 2
4 4
3
-3 0
-5 1
2 2
4
9 -1
2 0
3 1
-2 2

输出样例1

5 + 1x^1 + 2x^2 + 3x^3
(-5) + (-1)x^1 + 6x^2 + 4x^4
8x^2 + 3x^3 + 4x^4
(-3) + (-5)x^1 + 2x^2
9x^(-1) + 2 + 3x^1 + (-2)x^2
9x^(-1) + (-1) + (-2)x^1


AC代码

#include<bits/stdc++.h>
using namespace std;
class node
{
public:
    int xishu;
    int zhishu;
    node* next;
    node(int a = 0, int b = 0, node* c = NULL)
    {
        xishu = a;
        zhishu = b;
        next = c;
    }
};
class linknode
{
    node* head;
    int len;
public:
    linknode()
    {
        head = new node;
        len = 0;
    }
    linknode(int n)
    {
        len = n;
        head = new node;
        node* q = head;//尾指针
        for (int i = 1; i <= n; i++)
        {
            int a, b;
            cin >> a >> b;
            node* p = new node(a, b);
            p->next = q->next;
            q->next = p;
            q = q->next;
        }
    }
    //尾插法
    void linkinsert(node* s)
    {
        node* p = head;
        while (p->next != NULL)
        {
            p = p->next;
        }
        //p(最后一个)  p->next=NULL
        node* pp = new node;
        *pp = *s;
        pp->next = p->next;
        p->next = pp;
        len++;
    }
    friend linknode operator +(linknode& la, linknode& lb)
    {
        linknode l;
        node* p = la.head->next;
        node* q = lb.head->next;
        while (p && q)
        {
            if (p->zhishu == q->zhishu)
            {
                int tt = q->xishu + p->xishu;
                if (tt)
                {
                    node* s = new node(tt, p->zhishu);
                    l.linkinsert(s);//尾部插入
                }
                p = p->next;
                q = q->next;
            }
            else if (p->zhishu < q->zhishu)
            {
                l.linkinsert(p);
                p = p->next;
            }
            else
            {
                l.linkinsert(q);
                q = q->next;
            }
        }
        while (p)
        {
            l.linkinsert(p);
            p = p->next;
        }
        while (q)
        {
            l.linkinsert(q);
            q = q->next;
        }
        return l;
    }
    void display()
    {
        node* p = head->next;
        while (p)
        {
            if (p->xishu < 0)
            {
                cout << "(" << p->xishu << ")";
            }
            else
            {
                cout << p->xishu;
            }
            if (p->zhishu > 0)
            {
                cout << "x^" << p->zhishu;
            }
            else if (p->zhishu < 0)
            {
                cout << "x^(" << p->zhishu << ")";
            }
            p = p->next;
            if (p != NULL)cout << " + ";
        }
        cout << endl;
    }
};
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        linknode q1(n);
        q1.display();
        cin >> n;
        linknode q2(n);
        q2.display();
        (q1 + q2).display();
    }
    return 0;
}

F. DS链表—学生宿舍管理(双向列表容器List)

题目描述

假设某校有20间宿舍,宿舍编号101,102,...,120。每间只住一名学生。初始部分宿舍已用。用两个链表(已用宿舍链表和可用宿舍链表)维护宿舍的管理,实现宿舍分配、宿舍交回。

约定已用宿舍链表按宿舍号升序链接。初始可用宿舍链表也按宿舍号升序链接。

宿舍分配从可用宿舍链表中摘取第一间宿舍分配给学生。学生交回的宿舍挂在可用宿舍链表最后。

备注:使用list容器或静态链表。不用考虑宿舍分配和交回不成功的情况。

输入

初始宿舍状态,第一行输入n,表示已用宿舍n间

后跟n行数据,每行格式为:学生姓名 宿舍号 

操作次数m,后跟m行操作,操作格式如下:

assign 学生  //为学生分配宿舍,从可用宿舍链表头摘取一间宿舍,

//按宿舍号升序挂在已用宿舍链表中。

return  宿舍号   //学生退宿舍,删除已用宿舍链表中对应结点,

//挂在可用宿舍链表尾部。

display_free   //输出可用宿舍链表信息。

display_used   //输出已用宿舍链表信息。

输出

display_free依次输出当前可用宿舍链表中的宿舍号,具体格式见样例。

display_used依次输出当前已用宿舍链表中的宿舍号,具体格式见样例。

样例查看模式 

正常显示查看格式

输入样例1 

5
李明  103
张三  106
王五  107
钱伟  112
章立  118
8
assign 李四
assign 赵六
return 118
return 101
assign 马山
display_used
assign 林立
display_free

输出样例1

赵六(102)-李明(103)-马山(104)-张三(106)-王五(107)-钱伟(112)
108-109-110-111-113-114-115-116-117-119-120-118-101

AC代码

#include<bits/stdc++.h>
using namespace std;
int st[200];
struct kenode
{
    string name;
    int num;
    kenode* next;
    kenode(string s = "", int a = 0, kenode* c = NULL)
    {
        name = s;
        num = a;
        next = c;
    }
};
struct yinode
{
    int data;
    yinode* next;
    yinode(int a = 0, yinode* b = NULL)
    {
        data = a;
        next = b;
    }
};
class llink
{
    int kelen;
    int yilen;
    kenode* kehead;
    yinode* yihead;
public:
    llink(int n)
    {
        kelen = n;
        kehead = new kenode;
        kenode* q = kehead;
        for (int i = 0; i < kelen; i++)
        {
            string ss;
            int a;
            cin >> ss >> a;
            kenode* p = new kenode(ss, a);
            st[a] = 1;
            p->next = q->next;
            q->next = p;
            q = q->next;
        }
        yihead = new yinode;
        yinode* qq = yihead;
        yilen = 20 - kelen;
        for (int i = 101; i <= 120; i++)
        {
            if (st[i] == 0)
            {
                yinode* pp = new yinode(i);
                pp->next = qq->next;
                qq->next = pp;
                qq = qq->next;
            }
        }
    }
    int deleteyinode()
    {
        yinode* p = yihead->next;
        yihead->next = p->next;
        yilen--;
        return p->data;
    }
    void addkenode(kenode* d)
    {
        kenode* p = kehead->next;
        kenode* s = new kenode;
        *s = *d;
        while (p != NULL)
        {
            if (p->num < s->num && (p->next->num > s->num || p->next == NULL))
            {
                s->next = p->next;
                p->next = s;
                kelen++;
                return;
            }
            p = p->next;
        }
        p = kehead;
        d->next = p->next;
        p->next = d;
        kelen++;
    }
    void addyinode(int n)
    {
        yinode* p = yihead;
        while (p->next != NULL)
        {
            p = p->next;
        }
        yinode* pp = new yinode(n);
        pp->next = p->next;
        p->next = pp;
        yilen++;
    }
    void shifan(int n)
    {
        kenode* p = kehead;
        while (p != NULL)
        {
            if (p->next->num == n)
            {
                addyinode(n);
                p->next = p->next->next;
                kelen--;
                break;
            }
            p = p->next;
        }
    }
    void display_used()
    {
        kenode* p = kehead->next;
        while (p->next)
        {
            cout << p->name << "(" << p->num << ")-";
            p = p->next;
        }
        cout << p->name << "(" << p->num << ")" << endl;
    }
    void display_free()
    {
        yinode* pp = yihead->next;
        while (pp->next)
        {
            cout << pp->data << "-";
            pp = pp->next;
        }
        cout << pp->data << endl;
    }
    void assign(string nn)
    {
        kenode* p = new kenode(nn, deleteyinode());
        addkenode(p);
    }
};
int main()
{
    int nn;
    cin >> nn;
    llink ll(nn);
    int m;
    cin >> m;
    while (m--)
    {
        string ss;
        cin >> ss;
        string nn;
        if (ss == "display_used")
        {
            ll.display_used();
        }
        else if (ss == "display_free")
        {
            ll.display_free();
        }
        else if (ss == "assign")
        {
            cin >> nn;
            ll.assign(nn);
        }
        else if (ss == "return")
        {
            int aa;
            cin >> aa;
            ll.shifan(aa);
        }
    }
    return 0;
}

  • 24
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值