《算法》作业

《算法》第一次作业:

Q1: Show the contents of the id[] array and the number of times the array is accessed for each input pair when you use quick-find for the sequence 9-0 3-4 5-8 7-2 2-1 5-7 0-3 4-2.

显示id[]数组的内容,以及对序列9-0 3-4 5-8 7-2 2-1 5-7 0-3 4-2使用快速查找时,每个输入对访问数组的次数;

  1. QuickFindUF(10):

    []0123456789
    id[]0123456789
  2. union(9, 0):

    访问次数:13次;

    []0123456789
    id[]0123456780
  3. union(3, 4):

    访问次数:13次;

    []0123456789
    id[]0124456780
  4. union(5, 8):

    访问次数:13次;

    []0123456789
    id[]0124486780
  5. union(7, 2):

    访问次数:13次;

    []0123456789
    id[]0124486280
  6. union(2, 1):

    访问次数:14次;

    []0123456789
    id[]0114486180
  7. union(5, 7):

    访问次数:14次;

    []0123456789
    id[]0114416110
  8. union(0, 3):

    访问次数:14次;

    []0123456789
    id[]4114416114
  9. union(4, 2):

    访问次数:16次;

    []0123456789
    id[]1111116111
代码实现:
  • vim quickfind.cc:

    #include <iostream>
    #include <vector>
      
    using std::vector;
    using std::cout;
    using std::endl;
    using std::cin;
      
    int main()
    {
            int n = 0;
            cin >> n;
            vector<int> id(n);
            int i = 0;
            for ( vector<int>::iterator iter = id.begin(); iter != id.end(); ++iter )
            {
                    *iter = i;
                    i++;
            }
            int p = 0;
            int q = 0;
            while( cin >> p >> q ) {
              			int c = 0; // 记录访问数组次数;
                    int pid = id[p];
              			c++;
                    int qid = id[q];
              			c++;
                    cout << "id[] is ";
                    for ( vector<int>::iterator iter = id.begin(); iter != id.end(); ++iter )
                    {
                            if ( *iter == pid ){ *iter = qid; c++; }
                      	    c++;
                            cout << *iter;
                    }
             				cout << " and c is" << c << endl;
            }
            return 0;
    }
    
  • vim quickfind_input.txt

    10
    9 0
    3 4
    5 8
    7 2
    2 1
    5 7
    0 3
    4 2
    
  • vim quickfind_output.txt

  • gcc -l c++ -o quickfind quickfind.cc;

  • ./quickfind <quickfind_input.txt >quickfind_output.txt

  • 输出结果:

   	id[] is 0123456780 and c is 13
   	id[] is 0124456780 and c is 13
   	id[] is 0124486780 and c is 13
   	id[] is 0124486280 and c is 13
   	id[] is 0114486180 and c is 14
   	id[] is 0114416110 and c is 14
   	id[] is 4114416114 and c is 14
   	id[] is 1111116111 and c is 16

Q2: Do Exercise 1.5.1, but use quick-union (英文教材224页,中文教材141页). In addition, draw the forest of trees represented by the id[] array after each input pair is processed.use quick-union for the sequence 9-0 3-4 5-8 7-2 2-1 5-7 0-3 4-2.

依附根节点,左根连右根;

访问次数 = p查找根的次数 + q查找根的次数 + 1(将根连到一起);

  1. QuickUnionUF(10):

    []0123456789
    id[]0123456789
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
  2. union(9, 0):

    访问次数:1 + 1 + 1 = 3次;

    []0123456789
    id[]0123456780
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
  3. union(3, 4):

    访问次数:1 + 1 + 1 = 3次;

    []0123456789
    id[]0124456780
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
  4. union(5, 8):

    访问次数:1 + 1 + 1 = 3次;

    []0123456789
    id[]0124486780
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
  5. union(7, 2):

    访问次数:1 + 1 + 1 = 3次;

    []0123456789
    id[]0124486280
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
  6. union(2, 1):

    访问次数:1 + 1 + 1 = 3次;

    []0123456789
    id[]0114486280
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
  7. union(5, 7):

    访问次数:2 + 3 + 1 = 6次;

    []0123456789
    id[]0114486210
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
  8. union(0, 3):

    访问次数:1 + 2 + 1 = 4次;

    []0123456789
    id[]4114486210
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
  9. union(4, 2):

    访问次数:1 + 2 + 1 = 4次;

    []0123456789
    id[]4114186210
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
代码实现:
#include <iostream>
#include <vector>
  
using std::vector;
using std::cout;
using std::endl;
using std::cin;
  
int main()
{
        int n = 0;
        cin >> n;
        vector<int> id(n);
        int i = 0;
        for ( vector<int>::iterator iter = id.begin(); iter != id.end(); ++iter )
        {
                *iter = i;
                i++;
        }
        int p = 0;
        int q = 0;
        while( cin >> p >> q ) {
          			int c = 0; // 记录数组访问次数;
          			//如果p或q位置存的不是自己的标号,说明自己不是父节点,向上追溯;
          			int k = 0;
          			while ( ( k = id[p] ) != p ){
                  p = k;
                  c++;
                }
          			c++; // 虽然判断相等,没有进入循环,但是还是对数组进行了一次访问;
          			while ( ( k = id[q] ) != q ){
                  q = k;
                  c++;
                }
          			c++;
          			id[p] = q; // p的根连到q的根上;
          			c++;
                cout << "id[] is ";
                for ( vector<int>::iterator iter = id.begin(); iter != id.end(); ++iter )
                {
                        cout << *iter;
                }
                cout << " and c is " << c << endl;
        }
        return 0;
}

输出:

id[] is 0123456780 and c is 3
id[] is 0124456780 and c is 3
id[] is 0124486780 and c is 3
id[] is 0124486280 and c is 3
id[] is 0114486280 and c is 3
id[] is 0114486210 and c is 6
id[] is 4114486210 and c is 4
id[] is 4114186210 and c is 4

Q3:Do Exercise 1.5.1, but use weighted quick-union,use weighted quick-union for the sequence 9-0 3-4 5-8 7-2 2-1 5-7 0-3 4-2.
  1. QuickWeightUnionUF(10):

    []0123456789
    id[]0123456789
    sz[]1111111111
  2. union(9, 0):

    访问id[]次数:3次;

    []0123456789
    id[]9123456789
    sz[]1111111112
  3. union(3, 4):

    访问id[]次数:3次;

    []0123456789
    id[]9123356789
    sz[]1112111112
  4. union(5, 8):

    访问id[]次数:3次;

    []0123456789
    id[]9123356759
    sz[]1112121112
  5. union(7, 2):

    访问id[]次数:3次;

    []0123456789
    id[]9173356759
    sz[]1112121212
  6. union(2, 1):

    访问id[]次数:4次;

    []0123456789
    id[]9773356759
    sz[]1112121312
  7. union(5, 7):

    访问id[]次数:3次;

    []0123456789
    id[]9773376759
    sz[]1112121512
  8. union(0, 3):

    访问id[]次数:4次;

    []0123456789
    id[]9779376759
    sz[]1112121514
  9. union(4, 2):

    访问id[]次数:6次;

    []0123456789
    id[]9779376757
    sz[]1112121914
代码实现:
#include <iostream>
#include <vector>
  
using std::vector;
using std::cout;
using std::endl;
using std::cin;
  
int main()
{
        int n = 0;
        cin >> n;
        vector<int> id(n);
  			vector<int> sz(n, 1); // 初始权重数组的初始权重为1;
        int i = 0;
        for ( vector<int>::iterator iter = id.begin(); iter != id.end(); ++iter )
        {
                *iter = i;
                i++;
        }
        int p = 0;
        int q = 0;
        while( cin >> p >> q ) {
          		int idc = 0; //对id数组的访问次数;
          		int szc = 0; //对sz数组的访问次数;
          		while ( id[p] != p ){
                	p = id[p];
                	idc++;
                }
          		idc++;
          		while ( id[q] != q ){
                q = id[q];
                idc++;
        }
          			idc++;
          			// 前面的查找根和quickunion相同,但是合并根要根据sz数组的值;
          			// if ( sz[p] <= sz[q] ){ id[p] = q; sz[q] += sz[p]; }
          			int szp, szq;
          			if ( (szp = sz[p]) < (szq = sz[q]) ){ 
                  		id[p] = q; 
                  		sz[q] += szp; 
                  		idc++; 
                  		szc += 3;
                }
          			else { 
                  		id[q] = p; 
                  		sz[p] += szq; 
                  		idc++;
                  		szc += 3; //访问sz数组两次,赋值sz数组一次,一共三次;
                }
                cout << "id[] is ";
                for ( vector<int>::iterator iter = id.begin(); iter != id.end(); ++iter )
                {
                        cout << *iter;
                }
          		cout << "; sz[] is ";
                for ( int i = 0; i != n; ++i)
                {
                        cout << sz[i];
                }
                cout << "; idc is " << idc << "; szc is " << szc << endl;	
        }
        return 0;
}

结果:

id[] is 9123456789; sz[] is 1111111112; idc is 3; szc is 3
id[] is 9123356789; sz[] is 1112111112; idc is 3; szc is 3
id[] is 9123356759; sz[] is 1112121112; idc is 3; szc is 3
id[] is 9173356759; sz[] is 1112121212; idc is 3; szc is 3
id[] is 9773356759; sz[] is 1112121312; idc is 4; szc is 3
id[] is 9773376759; sz[] is 1112121512; idc is 3; szc is 3
id[] is 9779376759; sz[] is 1112121514; idc is 4; szc is 3
id[] is 9779376757; sz[] is 1112121914; idc is 6; szc is 3
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值