我接受字符串格式的输入。然后我将每个数字转换为整数,并将每个数字存储在链表节点中。我本可以使用数组,但避免使用,因为它们有内存限制并且是静态的。请告诉我下面的代码哪里出错了?
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
struct ll{
int digit;
int place;
struct ll *next;
};
typedef struct ll node;
node *insert(node *head,int dig, int plac)//to insert new nodes{
if(head==NULL){
head=(node *)malloc(sizeof(node));
head->digit=dig;
head->place=plac;
head->next=NULL;
return head;
}
else{
head->next=insert(head->next,dig,plac);
return head;
}
}
void print(node *a)//to print all the nodes in the linked list{
node *temp;
temp=a;
while(temp!=NULL){
printf("%dn",temp->digit);
temp=temp->next;
}
}
node *string_to_trainofdig(char h[],node *head){ //converting a string to integer digits and storing them individually in the linked list
int q,i;
q=strlen(h);int j;node *temp;temp=(node *)malloc(sizeof(node));
printf("value of q is %dn",q);
for(i=q-1;i>=0;i--){
printf("value of i %dn",i);
switch(h[i]){
case '0':j=0;break;
case '1':j=1;break;
case '2':j=2;break;
case '3':j=3;break;
case '4':j=4;break;
case '5':j=5;break;
case '6':j=6;break;
case '7':j=7;break;
case '8':j=8;break;
case '9':j=9;break;
}
printf("j is %dn",j);
temp=insert(head,j,i);
head=temp;
}
return temp;
}
int count(node *q){ //counting the total number of nodes in a linked list
int p=0;;
node *w;
w=q;
while(w!=NULL){
p++;
w=w->next;
}
return p;
}
int pos(node *a, int y){ //this function returns the digit stored in a //particular node (specified by its position)
y--;
node *temp; temp=a;
if(a==NULL){
return 0;
}
else{
while(temp!=NULL || y!=0){
temp=temp->next;
y--;
}
if(temp==NULL){
return 0;
}
else if(y==0){
return temp->digit;
}
}
}
node *modify(node *a,int value,int posi){ /*inserts nodes and assigns them //values if empty (NULL) but modifies the value stored in that position in the //linked list if not NULL*/
node *temp; temp=a; posi--;
if(a==NULL){
return insert(a,value,posi);
}
else{
while(temp!=NULL || posi!=0){
temp=temp->next;
posi--;
}
if(temp==NULL){
return NULL;
}
else if(posi==0){
temp->digit=value;
}
return a;
}
}
char *mult(node *a,node *b){ //taking two linked lists as parameters and multiplying them
char e[1000000];
node *as; node *bs;
as=a;bs=b;
int z,x,m,n,v,r;
m=0; n=0;
node *newe;node *newe2;
char er[1000000];
newe=NULL;
int s;
s=count(a)>count(b)?count(a):count(b);
as=count(a)>count(b)?a:b;//determines which linked list is bigger and //assigns that to as
bs=count(a)>count(b)?b:a;//bs is smaller of the two linkedc lists
int fr=0;int ca=0; int i=0;
while(bs!=NULL)//main algorithm{
i=fr;//fr is initially 0
while(as!=NULL){
m=as->digit*bs->digit+m;//m is zero initially
n=m%10;
m=m/10;
ca=(pos(newe,i));// ca gets the value stored in the ith position of node //newe---->will be 0 initially since NULL
newe=modify(newe,n+ca,i);
as=as->next;i++;
}
as=count(a)>count(b)?a:b;
bs=bs->next;
fr++;//increments fr so that i comes back to fr
}
}
main(){
char d[1000]; char p[1000];
scanf("%s",d);
scanf("%s",p);
int q,w;
node *l,*u; l=NULL; u=NULL;
l=string_to_trainofdig(d,l);
u=string_to_trainofdig(p,u);
print(l);
print(u);
char *t;
t=mult(l,u);
printf("donen");
}
链表(尤其是在这种情况下)的性能非常差。每次跟随链接(例如temp=temp->next;
),都可能是缓存未命中,并破坏现代(无序)CPU上的指令并行性,因为后续代码所依赖的temp
的新值要到之后才能知道。它们还倾向于将数据分散到各处(缓存局部性差),这使前两个问题变得更糟,并使线性迭代"不可预取"(不像"对于阵列中的每个元素",CPU可以简单地检测模式并在需要之前预取数据)。
对于大整数,将整数存储为"基数10"也会导致性能极差。这只是由效率较低的内存使用引起的(例如,在本可以存储0到255的值的每个字节中存储0到9的值)。主要问题是,大多数高级运算都有"每位数"开销(加法、减法、AND、OR)或"每位数平方"开销(乘法)。小基数(例如"基数10")意味着更多的数字,这意味着大量的开销。较大的基数(例如"基数4294967296")意味着更少的数字和更少的开销。除此之外,使用"2的幂"大小可以使用移位和掩蔽,而不是模数和除法(例如digit = temp%10; temp /= 10;
与digit = temp & 0xFF; temp >>= 8;
);并且使用"整整数"大小使其更加高效(digit = temp; temp >>= 32;
)。大体上要获得可接受的性能,您需要匹配CPU的本机大小-例如,在32位系统上使用"base4294967296",在64位系统上则使用"base18446744073709551616"。
如果你把这两者结合起来,你可能会得到更像的东西
typedef struct {
int current_digits;
int allocated_digits;
uint32_t digits[];
} BIG_INTEGER;
请注意,current_digits
和allocated_digits
字段可以避免一直调整数组的大小。例如:
#define EXTRA_DIGITS 16
if(number->current_digits + 1 < number->allocated_digits) {
number->allocated_digits = number->current_digits + 1 + EXTRA_DIGITS;
newsize = sizeof(BIG_INTEGER) + sizeof(uint32_t)*number->allocated_digits;
number = realloc(number, newsize);
}
number->digits[number->current_digits] = 0;
number->current_digits++;
对于乘法本身;它大致是这样的(假设32位或uint32_t
用于数字,根本没有测试):
uint64_t temp; // Must be double the size of a digit
for(i = 0; i < number1->current_digits; i++) {
for(j = 0; j < number2->current_digits; j++) {
temp = number1->digits[i] * number2->digits[j];
k = i+j;
while(temp != 0) {
temp = temp + result->digits[k];
result->digits[k] = temp; // Lower half only
temp = temp >> 32;
k++;
}
}
}
您可能可以将其转换为使用链表而不是数组;但是
如果你试图用任意长的整数进行整数数学运算,我建议你使用GMP库或类似的库,而不是自己做。
我本可以使用数组,但避免了,因为它们有内存限制,而且是静态
这是不对的。虽然您可以在C中将数组声明为静态块,但您可以根据需要简单地声明一个指针和malloc()空间(当然要记住free())。
请告诉我下面的代码哪里出错了?
当发布问题时,这种含糊的提问方式是不可取的。
您告诉我们正在发生的事情和您的期望,一些示例输入和输出或错误报告。