线性表定义及实现
线性表是最常用的数据结构,抽象上讲表是存储具有先后顺序元素数据的结构,实现上分为顺序表和链式表。
顺序表一般采用C语言中数组实现,数组中存储数据,依靠数据索引确定先后顺序信息,物理上存储连续。根据C中数组的定义,移动,动态申请空间,复制等操作,可以想象顺序表在处理动态变化线性表上的缺点。
链式表一般采用C语言中结构体struct实现,每个结构体节点除了存储数据,还存储元素先后顺序信息,物理上存储不连续;根据是否存储前置元素可分为单链表双链表等。插入,删除,移动等动态操作较为方便。
编程实例
问题及解决思路
projecteuler的Problem10求2000000以内所有素数的和,首先要找到2000000所有素数。判断一个是是否素数,如果采用比之小的数去除,则除法运行次数太多。所以建立一个素数链表,用该链表里的素数去除,判断是否素数;一旦是素数,插入或追加到该链表中,为判断后续数字做嫁衣。
详细介绍:https://segmentfault.com/a/11...
代码实现
结构定义
struct intNode;typedef struct intNode sIntNode;typedef sIntNode *pIntNode;struct intNode{ long long int data; pIntNode next; pIntNode prv;};
操作方法
//初始化pIntNode elrInitListInt(long long int data){ pIntNode tmp = NULL; tmp = (pIntNode)malloc(sizeof(sIntNode)); tmp->data = data; tmp->prv = tmp->next = tmp; return tmp;}//释放void elrPushListInt(pIntNode pList, long long int data){ pIntNode tmp = NULL; tmp = (pIntNode)malloc(sizeof(sIntNode)); tmp->data = data; tmp->next = pList; tmp->prv = pList->prv; pList->prv->next = tmp; pList->prv = tmp;}//追加元素void elrFreeListInt(pIntNode pList){ pIntNode tmp; while (pList->prv != pList){ tmp = pList->prv; pList->prv = tmp->prv; tmp->prv->next = pList; free(tmp); } free(pList); pList = NULL;}
素数全局变量初始化方法
pIntNode globalPrime;int globalPrimeCount;long long int globalPrimeNum;void initGlobalPrime(){ globalPrime = elrInitListInt(2); elrPushListInt(globalPrime, 3); elrPushListInt(globalPrime, 5); globalPrimeNum = 0; globalPrimeCount = 3;}void freeGlobalPrime(){ elrFreeListInt(globalPrime); globalPrimeNum = 0; globalPrimeCount = 0; }
判断是否素数
//优化:
//1.用链表的素数去除,减少除法运行次数,本质上应该就是Eratosthenes埃拉托斯特尼筛选法
//2.采用6n+1,6n+5才可能是素数,减少运行次数
int isPrime(const long int num){ pIntNode tmpPrimeNode; long int tmpNum; if (num <= globalPrimeNum * 6){ tmpPrimeNode = globalPrime; do{ if (num < tmpPrimeNode->data) break; if (tmpPrimeNode->data == num) return 1; tmpPrimeNode = tmpPrimeNode->next; }while(tmpPrimeNode != globalPrime); return 0; } else{ for (tmpNum = globalPrimeNum + 1; tmpNum * 6 <= num + 6; tmpNum += 1){ globalPrimeNum = tmpNum; long int test; int isDiv; test = tmpNum * 6 + 1; isDiv = 1; tmpPrimeNode = globalPrime; do{ if ((tmpPrimeNode->data * tmpPrimeNode->data) > test) break; if (! (test % tmpPrimeNode->data)){ isDiv = 0; break; } tmpPrimeNode = tmpPrimeNode->next; }while (tmpPrimeNode != globalPrime); if (isDiv){ elrPushListInt(globalPrime, test); globalPrimeCount++; } test = tmpNum * 6 + 5; isDiv = 1; tmpPrimeNode = globalPrime; do{ if ((tmpPrimeNode->data * tmpPrimeNode->data) > test) break; if (! (test % tmpPrimeNode->data)){ isDiv = 0; break; } tmpPrimeNode = tmpPrimeNode->next; }while (tmpPrimeNode != globalPrime); if (isDiv){ elrPushListInt(globalPrime, test); globalPrimeCount++; } } return isPrime(num); // if ((num == globalPrime->prv->data) || (num == globalPrime->prv->prv->data)) // return 1; // else // return 0; }}
找第n个素数
long long int findPrimeSumByNum(const long int num){ long int iSum= 0; pIntNode tmpPrimeNode; if (num > globalPrimeNum){ isPrime(num); } tmpPrimeNode = globalPrime; do{ iSum += tmpPrimeNode->data; tmpPrimeNode = tmpPrimeNode->next; }while ((globalPrime != tmpPrimeNode) && (num >= tmpPrimeNode->data)); return iSum;}