链表,是数据结构中很重要的一个章节,单链表和双链表的相关算法,也是考研的重点,下面学长为大家分享一下关于双链表操作的相关算法。
创建双向循环链表
1:创建头结点,新增结点,然后将头结点与创建的结点进行关联。
typedef int Status;//函数状态typedef int ElemType;//ElemType 根据实际情况而定typedef struct Node{ ElemType data; struct Node *prior;//前趋 struct Node *next;//后继 }Node;// 类型重定义typedef struct Node *Linklist;//创建双向链表Status creatLinkList(LinkList *L){ // 1。创建头结点,开辟一个空间; *L = (LinkList)malloc(sizeof(Node)); //判断是否创建成功 if(*L == NULL) return ERROR; (*L)->prior=NULL; //前趋置空 (*L)->next =NULL; //后趋置空 (*L) ->data =-1; //临时 //新增结点 LinkList p = *L; for(int i=0;i<10;i++){ //创建临时变量节点 LinkList temp = (linkList)malloc(sizeof(Node)); if(temp ==NULL) return ERROR;//容错 //设置前趋后趋和数据 temp->prior = NULL; temp->next = NULL; temp->data =i; //创建关系 p-temp p->next = temp; temp->prior = p; //p 后移 p= p->next; } return OK;}void display(LinkList L){ //不打印头结点 跳过L; LinkList temp = L->next; if (temp == NULL){ return; } while (temp){ printf("打印数据 %d",temp->data); temp = temp->next;//temp 后移 }}int main(int argc,const char* argv[]){ Status isStatus = 0; LinkList L; //创建双向循环列表 isStatus = creatLinkList (&L); //打印列表 display(L);}
双向链表的插入
双向列表的插入:
首先判断插入位置是否是合法。
然后需要新建结点。
把p指向头结点
循环找到要插入的位置
判断插入位置是否是超过链表长度
判断插入位置是否是结尾 (结尾:将链表尾部结点的next-->插入节点;将插入节点的prior -->尾部结点)
对于非尾部结点:【1:p->next = temp; temp->prior = p ; p->next->prior = temp ; temp->next = p->next】插入节点的前趋跟后趋 分别指向插入结点的后趋及插入节点后节点的前趋。
Status insertList (LinkList *L, int i,ElemType data){ if(i<1) return ERROR; LinkList temp = (LinkList)malloc(sizeof(Node)); temp->data = data; temp->next = NULL; temp->prior = NULL; LinkList p = *L; for(int j=1 ; j< i && p;j++){ p = p->next; } if(p==NULL) return ERROR; if(p->next ==NULL){ P->next = temp; temp->prior = p; }else{ p->next = temp; temp->prior = p; temp->next = p->next; p->next->prior = temp; } return OK;}
双向链表的删除
删除列表指定位置的结点
判断双向列表是否为空,如果是空就直接返回错误
将指针p移动到删除元素位置前一个
判断 k > i 或者 p ==null 返回错误
创建临时删除指针delTemp 指向要删除的结点,并将要删除的结点data 传给*e , 返回
p->next 等于要删除的结点的下一个结点。
如果删除结点的下一个节点不为空,则将要删除的下一个结点的前趋指针赋值P
删除delTemp节点;
//5.4 删除双向链表指定位置上的结点Status ListDelete(LinkList *L, int i, ElemType *e){ int k = 1; LinkList p = (*L); //1.判断双向链表是否为空,如果为空则返回ERROR; if (*L == NULL) { return ERROR; } //2. 将指针p移动到删除元素位置前一个 while (k < i && p != NULL) { p = p->next; k++; } //3.如果k>i 或者 p == NULL 则返回ERROR if (k>i || p == NULL) { return ERROR; } //4.创建临时指针delTemp 指向要删除的结点,并将要删除的结点的data 赋值给*e,带回到main函数 LinkList delTemp = p->next; *e = delTemp->data; //5. p->next 等于要删除的结点的下一个结点 p->next = delTemp->next; //6. 如果删除结点的下一个结点不为空,则将将要删除的下一个结点的前驱指针赋值p; if (delTemp->next != NULL) { delTemp->next->prior = p; } //7.删除delTemp结点 free(delTemp); return OK; }
删除双向链表指定的元素
遍历双向循环列表链表
判断当前结点的数据域和data是否一致,如相等,则删除当前结点。
删除:修改被删除结点的后继结点。修改被删除结点的后继结点的前趋。
释放被删除的结点。
Status LinkLisTDeletValue(LinkList * L,int data){ LinkList p = *L; //遍历双向列表 while (p){ if(p->data ==data){ p->prior->next = p->next; if (p->next != NULL){ P->next->prior = p->prior; } //释放被删除的节点P free(p); //退出循环 break; } p = p->next; }}
双向链表查找元素
int selectElem (LinkList L,ElemType elem){ //头结点的下一个节点开始 LinkList p = L->next; int i = 1;//移动跟踪 while (p){ //遍历查找到数据,返回索引值 if (p->data == elem){ return i; } //索引值自增 i++; p = p->next; } return -1;}
双向链表中更新结点
Status replaceLinkList(LinkList * L,int index,ElemType newType){ //p 首元结点开始 LinkList p =(*L)->next; for (int i=1;i<=index;i++){ p=p->next; } p->data = newElem; return OK;}
算法比较基础,可以结合图形来理解算法,希望能帮助到大家!