HBU DS 1-10 链表去重 (20分)

1-10 链表去重 (20分)

给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。

输入格式:

输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤105,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 -1 来表示。

随后 N 行,每行按以下格式描述一个结点:

地址 键值 下一个结点

其中地址是该结点的地址,键值是绝对值不超过104的整数,下一个结点是下个结点的地址。

输出格式:

首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。

输入样例:

00100 5
99999 -7 87654
23854 -15 00000
87654 15 -1
00000 -15 99999
00100 21 23854

输出样例:

00100 21 23854
23854 -15 99999
99999 -7 -1
00000 -15 87654
87654 15 -1

这道题卡了我好久,呼~

我刚开始的思路就很。。。简单。就 先用数组把他们存下来,然后再排序到链表里,然后再for循环,两层循环,删除。

然后我就写,然后样例过了,然后有俩超时,我就想,是不是从数组往链表排序那太费事了。然后就想着不行就输入也用链表吧,最后我忘过没过了,可能还是超时?因为现在那个题目集已经结束了,我也不能再提交看看是什么情况,应该没AC。然后我就看网上的一个办法,特别厉害。然后用那个办法写了一下,过了。然后第二天我自己又用链表写了一下,这次第一次提交,有两个点过不去,然后我突然发现那个key的值是小于等于10000。然后数组长度加了个1,就AC了。呼~

思路:总而言之学到了几个东西:

  • 删除元素,不非得用两层for循环。建立一个数组,先都设置为0,索引就是这个数的值。具体算法是:如果循环到一个数,他还没有出现过,就把他置为1,表示这个数出现过了。循环到下一个相同的数,发现数组里对应的值是1,就把他删除。复杂度直接成了O(N)了。
  • 就是直接可以把那个五位数的地址,当成一个数组的索引。具体看代码把。
  • 不用管下一个数的地址,删除完之后,这个节点存的下一个地址直接输出下一个地点的对应的地址。

代码没有过的

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#define nullptr NULL
using namespace std;
typedef struct Node *List;
struct Node
{
    int thisAddress;
    int key;
    int nextAddress;
    List next;
};
int firstAddress, N;
void Read(List L);
void Sort(List L, List L0);
void Print(List L);
List DelRepeat(List L);
int main()
{
    List L0 = (List)malloc(sizeof(struct Node));
    L0->next = nullptr;
    Read(L0);

    List L = (List)malloc(sizeof(struct Node));
    L->next = nullptr;
    //排序到链表
    Sort(L, L0);

    List outL = DelRepeat(L);

    Print(L);
    Print(outL);
}
void Read(List L)
{
    List temp = L;

    cin >> firstAddress >> N;

    List currNode;
    for (int i = 0; i < N; i++)
    {
        currNode = (List)malloc(sizeof(struct Node));
        cin >> currNode->thisAddress >> currNode->key >> currNode->nextAddress;
        temp->next = currNode;
        temp = temp->next;
        temp->next = nullptr;
    }
}
void Sort(List L, List L0)
{
    List temp = L;
    List temp_next = NULL;
    List temp_pre = L0;

    int pre = firstAddress;
    List tempL0;
    do
    {

        tempL0 = L0->next;
        temp_pre = L0;
        while (tempL0)
        {

            if (tempL0->thisAddress == pre)
            {
                temp_pre->next = tempL0->next;
                //tempL0删除
                temp->next = tempL0;
                temp = temp->next;
                temp->next = nullptr;

                pre = temp->nextAddress;
                //temp添加

                break;
            }
            temp_pre = tempL0;
            tempL0 = tempL0->next;
        }
    } while (pre != -1);
}
void Print(List L)
{
    List temp = L->next;
    while (temp)
    {
        if (temp->nextAddress != -1)
            printf("%05d %d %05d\n", temp->thisAddress, temp->key, temp->nextAddress);
        else
            printf("%05d %d -1\n", temp->thisAddress, temp->key);
        temp = temp->next;
    }
}
List DelRepeat(List L)
{
    List DelL = (List)malloc(sizeof(struct Node));
    DelL->next = nullptr;
    List tempL = L->next, tempDelL = DelL; //debug2 这刚开始写成L了
    while (tempL)
    {
        int absnum = abs(tempL->key);
        List pre = tempL;
        List tempL_2 = tempL->next;

        while (tempL_2)
        {
            if (abs(tempL_2->key) == absnum)
            {
                tempDelL->next = tempL_2;
                tempDelL->nextAddress = tempL_2->thisAddress; //
                tempL_2 = tempL_2->next;

                tempDelL->next->next = nullptr;
                tempDelL->next->nextAddress = -1; //

                tempDelL = tempDelL->next; //debug1这没有这个语句

                pre->next = tempL_2;
                //这有个段错误
                if (tempL_2 == nullptr)
                    pre->nextAddress = -1;
                else
                {
                    pre->nextAddress = tempL_2->thisAddress; //
                }
            }
            else
            {
                pre = tempL_2;
                tempL_2 = tempL_2->next;
            }
        }
        tempL = tempL->next;
    }
    return DelL;
}

代码过了的_按照大佬的代码写的

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
#define MaxN 100000

struct Node
{
    int address;
    int key;
    int next;
    int num;
} Arr[MaxN];
bool isExist[MaxN];
bool cmp(Node n1, Node n2)
{
    return n1.num < n2.num;
}
int main()
{
    for (int i = 0; i < MaxN; i++)
    {
        Arr[i].num = 2 * MaxN;
    }
    int n, first, pre;
    cin >> first >> n;
    pre = first;
    int a;
    for (int i = 0; i < n && pre != -1; i++)
    {
        scanf("%d", &a);
        scanf("%d %d", &Arr[a].key, &Arr[a].next);
        Arr[a].address = a;
        pre = a;
    }
    int cnt1 = 0, cnt2 = 0;
    for (int i = first; i != -1; i = Arr[i].next)
    {
        if (!isExist[abs(Arr[i].key)])
        {
            isExist[abs(Arr[i].key)] = true;
            Arr[i].num = cnt1++;
        }
        else
        {
            Arr[i].num = MaxN + cnt2++;
        }
    }
    sort(Arr, Arr + MaxN, cmp);
    for (int i = 0; i < cnt1 + cnt2; i++)
    {
        if (i != cnt1 - 1 && i != cnt1 + cnt2 - 1)
        {
            printf("%05d %d %05d\n", Arr[i].address, Arr[i].key, Arr[i + 1].address);
        }
        else
        {
            printf("%05d %d -1\n", Arr[i].address, Arr[i].key);
        }
    }
}

代码过了的_链表写的

#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef struct Node *List;
struct Node
{
    int address;
    int key;
    int nextaddress;
    List next;
};
int firstAddress, N;
bool isExited[10001]; //默认false
List Read();
List Sort(List L);
List DelRepeat(List L);
List PrintL(List L);
int main()
{
    List rawL = Read();
    List sortedL = Sort(rawL);
    List deledL = DelRepeat(sortedL);
    PrintL(sortedL);
    PrintL(deledL);
}
List Read()
{
    scanf("%d %d", &firstAddress, &N);
    List L = (List)malloc(sizeof(Node)), tmp, s;
    L->next = NULL;
    tmp = L;

    for (int i = 0; i < N; i++)
    {
        s = (List)malloc(sizeof(Node));
        scanf("%d %d %d", &(s->address), &(s->key), &(s->nextaddress));
        s->next = NULL;

        tmp->next = s;
        tmp = s;
    }
    return L;
}
List Sort(List L)
{
    List L1 = L, L2 = (List)malloc(sizeof(Node)), t1, pre_t1; //L1 没有排序呢,L2 排好的
    List t2 = L2;
    L2->next = NULL;
    int pre = firstAddress;
    do
    {
        t1 = L1->next;
        pre_t1 = L1;
        while (t1)
        {
            if (t1->address == pre)
            {
                t2->next = t1;
                t2 = t2->next;
                pre_t1->next = t1->next; 
                t2->next = NULL;         
                pre = t2->nextaddress;
                break;
            }
            pre_t1 = t1;
            t1 = t1->next;
        }

    } while (pre != -1);

    return L2;
}
List DelRepeat(List L)
{
    List L1 = L, L2 = (List)malloc(sizeof(Node)), t1 = L1->next, t2 = L2, pre_t1 = L1; //L1 原来的除重剩下的,L2被删除的
    L2->next = NULL;
    while (t1)
    {
        if (!isExited[abs(t1->key)])
        {
            isExited[abs(t1->key)] = true;
            pre_t1 = t1;
            t1 = t1->next;
        }
        else
        {
            t2->next = t1;
            pre_t1->next = t1->next; //old del
            t1 = t1->next;           //t1 更新,pre_t1 没有变化

            t2 = t2->next; //t2 更新
            t2->next = NULL;
        }
    }
    return L2;
}
List PrintL(List L)
{
    List tmp = L->next;
    while(tmp)
    {
        if (tmp->next)
            printf("%05d %d %05d\n", tmp->address, tmp->key, tmp->next->address);
        else
            printf("%05d %d -1\n", tmp->address, tmp->key);
        tmp=tmp->next;
    }
}

呼,终于把三四周的卡到我的题,都写了一遍。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SVM算法通过将数据映射到高维空间,将数据分为两个类别。SVM算法的目标是找到一个超平面,可以将数据分为两个类别。SMO算法是一种优化算法,用于求解SVM中的二次规划问题。下面介绍如何使用SMO算法编写SVM对CIFAR-10数据进行分类。 首先,我们需要加载CIFAR-10数据集。CIFAR-10数据集包含10个类别的60000个32x32彩色图像。每个类别包含6000个图像。我们将使用Python中的pickle模块来加载数据集。以下是加载数据集的代码: ```python import pickle import numpy as np def unpickle(file): with open(file, 'rb') as fo: dict = pickle.load(fo, encoding='bytes') return dict def load_cifar10_data(): xs = [] ys = [] for j in range(5): d = unpickle('cifar-10-batches-py/data_batch_%d' % (j + 1)) x = d[b'data'] y = d[b'labels'] xs.append(x) ys.append(y) d = unpickle('cifar-10-batches-py/test_batch') xs.append(d[b'data']) ys.append(d[b'labels']) x = np.concatenate(xs) / np.float32(255) y = np.concatenate(ys) return x.reshape((len(x), -1)), np.array(y) ``` 接下来,我们将使用SMO算法来训练SVM模型。以下是使用SMO算法训练SVM模型的代码: ```python class SVM: def __init__(self, C, toler, kernel_opt=('linear', 0)): self.C = C self.toler = toler self.kernel_opt = kernel_opt def fit(self, X, y): n_samples, n_features = X.shape alpha = np.zeros(n_samples) b = 0 kernel = kernel_set[self.kernel_opt[0]] K = np.zeros((n_samples, n_samples)) for i in range(n_samples): K[:, i] = kernel(X, X[i], self.kernel_opt[1]) iter = 0 while iter < max_iter: num_changed_alphas = 0 for i in range(n_samples): Ei = np.dot(alpha * y, K[:, i]) + b - y[i] if (y[i] * Ei < -self.toler and alpha[i] < self.C) or \ (y[i] * Ei > self.toler and alpha[i] > 0): j = np.random.choice([x for x in range(n_samples) if x != i]) Ej = np.dot(alpha * y, K[:, j]) + b - y[j] alpha_i_old, alpha_j_old = alpha[i], alpha[j] if y[i] != y[j]: L = max(0, alpha[j] - alpha[i]) H = min(self.C, self.C + alpha[j] - alpha[i]) else: L = max(0, alpha[i] + alpha[j] - self.C) H = min(self.C, alpha[i] + alpha[j]) if L == H: continue eta = 2.0 * K[i, j] - K[i, i] - K[j, j] if eta >= 0: continue alpha[j] -= y[j] * (Ei - Ej) / eta alpha[j] = min(alpha[j], H) alpha[j] = max(alpha[j], L) if abs(alpha[j] - alpha_j_old) < 1e-5: continue alpha[i] += y[i] * y[j] * (alpha_j_old - alpha[j]) b1 = b - Ei - y[i] * (alpha[i] - alpha_i_old) * K[i, i] - \ y[j] * (alpha[j] - alpha_j_old) * K[i, j] b2 = b - Ej - y[i] * (alpha[i] - alpha_i_old) * K[i, j] - \ y[j] * (alpha[j] - alpha_j_old) * K[j, j] if 0 < alpha[i] < self.C: b = b1 elif 0 < alpha[j] < self.C: b = b2 else: b = (b1 + b2) / 2 num_changed_alphas += 1 if num_changed_alphas == 0: iter += 1 else: iter = 0 self.X = X self.y = y self.kernel = kernel self.alpha = alpha self.b = b def predict(self, X): n_samples, n_features = X.shape K = np.zeros((n_samples, len(self.X))) for i in range(n_samples): K[i, :] = self.kernel(self.X, X[i], self.kernel_opt[1]) y_pred = np.dot(self.alpha * self.y, K) + self.b return np.sign(y_pred) ``` 最后,我们使用以下代码来加载数据集并使用SMO算法训练SVM模型: ```python X, y = load_cifar10_data() y[y == 0] = -1 X_train, X_test = X[:50000], X[50000:] y_train, y_test = y[:50000], y[50000:] svm = SVM(C=1.0, toler=0.001, kernel_opt=('rbf', 1)) svm.fit(X_train, y_train) y_pred_train = svm.predict(X_train) y_pred_test = svm.predict(X_test) train_acc = np.mean(y_train == y_pred_train) test_acc = np.mean(y_test == y_pred_test) print('train_acc:', train_acc) print('test_acc:', test_acc) ``` 这样我们就使用SMO算法编写了SVM对CIFAR-10数据进行分类的代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值