线性表
//顺序表类型定义 #define ListSize 100 //表空间的大小可根据实际需要而定,这里假设为100 typedef int DataType; //DataType的类型可根据实际情况而定,这里假设为int typedef struct { DataType data[ListSize];//向量data用于存放表结点 int length;//当前的表长度 }SeqList; //顺序表上实现的基本运算 //1.表的初始化 void InitList(SeqList *L) {\\顺序表的初始化即将表的长度置为0 L->length=0; } //2.求表长 int ListLength(SeqList *L) { \\求表长只需返回L->length return L->length; } //3.取表中第i个结点 DataType GetNode(L,i) {\\取表中第i个结点只需返回和L->data[i-1]即可 if (i<1||i> L->length-1) Error("position error"); return L->data[i-1]; } //5. 插入 void InsertList(SeqList *L,DataType x,int i) {//将新结点 x插入L所指的顺序表的第i个结点ai的位置上 int j; if (i<1||i>L->length+1) Error("position error");//非法位置,退出运行 if (L->length>=ListSize) Error("overflow"); //表空间溢出,退出运行 for(j=L->length-1;j>=i-1;j--) L->data[j+1]=L->data[j];//结点后移 L->data[i-1]=x; //插入x L->Length++; //表长加1 } //6. 删除 void DeleteList(SeqList *L,int i) {//从L所指的顺序表中删除第i个结点ai int j; if(i<1||i>L->length) Error("position error"); //非法位置 for(j=i;j<=L->length-1;j++) L->data[j-1]=L->data[j]; //结点前移 L->length--; //表长减小 } //单链表的运算 // 1、建立单链表 //(1) 头插法建表 // 具体算法实现 LinkList CreatListF(void) {//返回单链表的头指针 char ch; LinkList head;//头指针 ListNode *s; //工作指针 head=NULL; //链表开始为空 ch=getchar(); //读入第1个字符 while(ch!='\n'){ s=(ListNode *)malloc(sizeof(ListNode));//生成新结点 s->data=ch; //将读入的数据放入新结点的数据域中 s->next=head; head=s; ch=getchar(); //读入下一字符 } return head; } //(2) 尾插法建表 // 具体算法实现 LinkList CreatListR(void) {//返回单链表的头指针 char ch; LinkList head;//头指针 ListNode *s,*r; //工作指针 head=NULL; //链表开始为空 r=NULL;//尾指针初值为空 ch=getchar(); //读入第1个字符 while(ch!='\n'){ s=(ListNode *)malloc(sizeof(ListNode));//生成新结点 s->data=ch; //将读入的数据放入新结点的数据域中 if (head!=NULL) head=s;//新结点插入空表 else r->next=s;//将新结点插到*r之后 r=s;//尾指针指向新表尾 ch=getchar(); //读入下一字符 }//endwhile if (r!=NULL) r->next=NULL;//对于非空表,将尾结点指针域置空head=s; return head; } //(3) 尾插法建带头结点的单链表 ③尾插法建带头结点链表算法 LinkList CreatListR1(void) {//用尾插法建立带头结点的单链表 char ch; LinkList head=(ListNode *)malloc(sizeof(ListNode));//生成头结点 ListNode *s,*r; //工作指针 r=head; // 尾指针初值也指向头结点 while((ch=getchar())!='\n'){ s=(ListNode *)malloc(sizeof(ListNode));//生成新结点 s->data=ch; //将读入的数据放入新结点的数据域中 r->next=s; r=s; } r->next=NULL;//终端结点的指针域置空,或空表的头结点指针域置空 return head; } //单链表的查找运算 (1)按序号查找 ListNode* GetNode(LinkList head,int i) {//在带头结点的单链表head中查找第i个结点,若找到(0≤i≤n), //则返回该结点的存储位置,否则返回NULL。 int j; ListNode *p; p=head;j=0;//从头结点开始扫描 while(p->next&&j<i){//顺指针向后扫描,直到p->next为NULL或i=j为止 p=p->next; j++; } if(i==j) return p;//找到了第i个结点 else return NULL;//当i<0或i>0时,找不到第i个结点 } //(2) 按值查找 ListNode* LocateNode (LinkList head,DataType key) {//在带头结点的单链表head中查找其值为key的结点 ListNode *p=head->next;//从开始结点比较。表非空,p初始值指向开始结点 while(p&&p->data!=key)//直到p为NULL或p->data为key为止 p=p->next;//扫描下一结点 return p;//若p=NULL,则查找失败,否则p指向值为key的结点 } //3.插入运算 void InsertList(LinkList head,DataType x,int i) {//将值为x的新结点插入到带头结点的单链表head的第i个结点的位置上 ListNode *p; p=GetNode(head,i-1);//寻找第i-1个结点 if (p==NULL)//i<1或i>n+1时插入位置i有错 Error("position error"); s=(ListNode *)malloc(sizeof(ListNode)); s->data=x;s->next=p->next;p->next=s; } //4.删除运算 void DeleteList(LinkList head,int i) {//删除带头结点的单链表head上的第i个结点 ListNode *p,*r; p=GetNode(head,i-1);//找到第i-1个结点 if (p==NULL||p->next==NULL)//i<1或i>n时,删除位置错 Error("position error");//退出程序运行 r=p->next;//使r指向被删除的结点ai p->next=r->next;//将ai从链上摘下 free(r);//释放结点ai的空间给存储池 } //1、循环链表 LinkList Connect(LinkList A,LinkList B) {//假设A,B为非空循环链表的尾指针 LinkList p=A->next;//①保存A表的头结点位置 A->next=B->next->next;//②B表的开始结点链接到A表尾 free(B->next);//③释放B表的头结点 B->next=p;//④ return B;//返回新循环链表的尾指针 } //1、双向链表(Double Linked List) //2、双向链表的结点结构和形式描述 //①结点结构(见上图a) //②形式描述 typedef struct dlistnode{ DataType data; struct dlistnode *prior,*next; }DListNode; typedef DListNode *DLinkList; DLinkList head; //①双链表的前插操作 void DInsertBefore(DListNode *p,DataType x) {//在带头结点的双链表中,将值为x的新结点插入*p之前,设p≠NULL DListNode *s=malloc(sizeof(DListNode));//① s->data=x;//② s->prior=p->prior;//③ s->next=p;//④ p->prior->next=s;//⑤ p->prior=s;//⑥ } //②双链表上删除结点*p自身的操作 void DDeleteNode(DListNode *p) {//在带头结点的双链表中,删除结点*p,设*p为非终端结点 p->prior->next=p->next;//① p->next->prior=p->prior;//② free(p);//③ }