带头节点的
ListInsert(LinkList &L , int index , ElemType e):实现数据的插入
ListIndexNextInsert(LNode *p , ElemType e):指定节点后插入数据
ListIndexPriorInsert(LNode *p , ElemType e):指定节点前插入数据
ListDelete(LinkList &L , int index , ElemType &e):删除指定位序的节点,并返回节点元素
ListDeletePoint(LNode *p):删除指定节点
GetElem(LinkList L , int index):查找指定位序的节点
LocateElem(LinkList L , ElemType e):按值查找
ListLenght(LinkList L):求链表的长度
List_TailInsert(LinkList &L):头插法创建链表
List_HeadInsert(LinkList &L):尾插法创建链表
fanzhuanList(LinkList &L):反转(逆置)链表
Init():初始化链表
bianliList(LinkList L):遍历链表
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; #define ElemType int typedef struct LNode{ ElemType data ; // 我这里用的是Int型的数据 struct LNode *next; }LNode , *LinkList;// 创建节点 LNode * GetElem(LinkList L , int index); bool ListIndexNextInsert(LNode *p , ElemType e); bool ListInsert(LinkList &L , int index , ElemType e){ // 插入 if(index < 1) return false; LNode *p = L; // 指向头节点 int j = 0 ; while(p != NULL && j < index-1){ // 插入位序的前一个 p = p->next; j++; } //上面的 这段代码可以用GetElem代替,封装,下面写的查找函数 /* 王道视频说可以用GetElem还查找p节点,这样子是不行的,视频用的是下面这一行语句 LNode *p = GetElem(L , index-1); 我们来走一下,我向插入的是index = 1 , index - 1 = 0 , GetElem 中有 if(i < 1) return false; 这里有问题了,会导致数据不能再第一个节点插入 如果想改的话,要动一些东西 */ /* if(p == NULL) return false; /* 下面的代码可以用这个来代替*/ //ElemType i = index ; return ListIndexNextInsert(p,index); /// 封装了 /*if(p == NULL) // 走到头了 return false; LNode *s = (LNode*)malloc (sizeof(LNode)); // 为插入的数据申请一个内存地址 s->data = e ; s->next = p->next; p->next = s; return true;*/ } bool ListIndexNextInsert(LNode *p , ElemType e){ // 指定的节点后插入数据 ,指定的节点 P if(p == NULL) return false; LNode *s = (LNode*)malloc(sizeof(LNode)); s->data = e; s->next = p->next; p->next = s; return true; } bool ListIndexPriorInsert(LNode *p , ElemType e){//指定的位置前插入数据 if(p == NULL) return true; // 先把节点插入在P节点的后面 , 在交换这连个结点的数据 LNode *s = (LNode*)malloc(sizeof(LNode)); s->data = e ; s->next = p->next; p->next = s; // 交换数据 ElemType temp = s->data; s->data = p->data; p->data = temp; return true; } bool ListDelete(LinkList &L , int index , ElemType &e){/// 带头节点的 // e 是返回被删除的元素 if(index < 1) return false; int j = 0 ; LNode *p = L; while(p != NULL && j < index-1){ p = p->next ; j++; } if(p == NULL||p->next == NULL) // 这里要注意一下后面这个判断条件,可以画图理解一下 return false; LNode *q = p->next; // 指向被删除的节点 e = q->data; p->next = q->next; free(q); return true; } bool ListDeletePoint(LNode *p){ // 删除指定节点 if(p == NULL) return true ; // 实质是把p节点的下一个节点的删除,把下一个节点的数据复制到P节点上来 // 如果删除的节点是链表的最后一个节点,就会出错, //解决办法是传入链表的第一个节点,重头遍历过来 , 这样写其实也可以了的 LNode *q = p->next; p->data = q->data; p->next = q->next; free(q); return true; } LNode * GetElem(LinkList L , int index){ if(index < 1) return NULL; LNode *p = L; int j = 0 ; while(p != NULL && j < index){ p = p->next; j++; } if(p == NULL) return NULL; // 没找到 return p; } LNode * LocateElem(LinkList L , ElemType e){ // 按值查找 LNode *p = L->next; while(p != NULL && p->data != e){ p = p->next; } if(p == NULL) return NULL; return p; } int ListLenght(LinkList L){ int len = 0; LNode *p = L->next; while(p!=NULL){ p = p->next; len++; } return len; } LinkList List_TailInsert(LinkList &L){//尾插法 // 这是带头节点的 int x ; // 插入的数据 LNode *r = L;//r用来返回记录最后一个节点的位置 printf("请输入数据(输入999表示结束):"); scanf("%d",&x); LNode *s; while(x!= 999){ s = (LNode*)malloc(sizeof(LNode)); s->data = x; s->next = NULL; r->next = s; r = s; scanf("%d",&x); } return L; } LinkList List_HeadInsert(LinkList &L){// 头插法 LNode *p = L; int x ; printf("请输入数据(输入888表示结束):"); scanf("%d" , &x); LNode *s ; while(x != 888){ s = (LNode*)malloc(sizeof(LNode)); s->data = x; s->next = p->next; p->next = s; // p 节点保持不动 scanf("%d",&x); } return L; } LinkList fanzhuanList(LinkList &L){/// 逆置链表 LNode *pre = NULL , *r = NULL; LNode *head = L ; // 记录一下头节点的地址,我们不对头节点进行操作,防止丢失 L = L->next; while(L!=NULL){ r = L->next; L->next = pre; pre = L; L = r; } /// L == NULL 时 , 链表的最后一个节点是pre ,把head 重新指向它 head->next = pre; // 把头节点和链表街上 return head ; } LNode* Init() // 初始化头节点 { LNode *temp ; temp = (LNode*)malloc(sizeof(LNode)); temp->data = -1 ; temp->next = NULL; return temp; } void bianliList(LinkList L) { LNode *p = L; while(p->next!=NULL){ /// 这是带头节点的链表的遍历 printf("%d " , p->next->data); p = p->next; } printf("\n"); } int main() { LinkList L = Init();/// 创建一个链表并初始化它 , 带头节点 LNode *p = L; printf("插入数据:\n"); for(int i = 1 ; i <= 5 ; i ++){ ListInsert(L , i , i); // 插入数据 } bianliList(L); /// 创建一个临时的节点,在这个节点之后插入一个数据,这个临时的节点指向头节点的下一个节点 LNode *temp_Node = p->next ; printf("插入数据(在指定的节点之后):10\n"); ListIndexNextInsert(temp_Node , 10); /// 在temp_Node 的后面插入 printf("数据插入后:"); bianliList(L); // 指定节点前插入数据 , 还是在temp_Node节点前 printf("插入数据(在指定的节点之前):8\n"); ListIndexPriorInsert(temp_Node , 8); printf("数据插入后:"); bianliList(L); printf("删除指定位置的元素(指定位置为 1):\n"); ElemType e; ListDelete(L , 1 , e) ; printf("删除的元素:%d\n" , e); bianliList(L); temp_Node = p->next; // printf("删除指定节点(指定第一个节点):\n"); ListDeletePoint(p->next); // temp_Node 就是向第一个节点的 bianliList(L); // 返回第 i 个元素 ,返回的是节点 temp_Node = GetElem(L , 3); // 返回第三个位置的节点 printf("第3个位置的元素为:%d\n", temp_Node->data); printf("按值查找(找5):\n"); temp_Node = LocateElem(L , 5); if(temp_Node != NULL) printf("找到5节点\n"); temp_Node = L; printf("求链表的长度:%d\n" , ListLenght(L)); printf("尾插法测试\n"); LinkList temp_tail = Init(); List_TailInsert(temp_tail); bianliList(temp_tail); printf("头插法测试\n"); LinkList temp_head = Init(); List_HeadInsert(temp_head); bianliList(temp_head); printf("反转链表测试\n"); bianliList(L); L = fanzhuanList(L); bianliList(L); return 0; }
带头节点的
相关的函数跟上面的一样,内容有点不一样
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; #define ElemType int typedef struct LNode{ ElemType data ; // 我这里用的是Int型的数据 struct LNode *next; }LNode , *LinkList;// 创建节点 bool ListInsert(LinkList &L , int index , ElemType e){/// 不带头节点的 if(index < 1 ) return false; if(index == 1){ // 不带头节点的要特判1这个位置,因为这是链表是空的 ,不能进行插入操作 LNode *s = (LNode*)malloc(sizeof(LNode)); s->data = e ; s->next = NULL; L = s ; // 把头节点带回去 return true; } LNode *p = L; int j = 1 ; while(p!=NULL && j < index-1){ p = p->next ; j++; } // 为插入的数据申请内存 LNode *s = (LNode*)malloc(sizeof(LNode)); s->data = e; s->next = p->next ; p->next = s; return s; } bool ListIndexNextInsert(LNode *p , ElemType e){ // 指定节点后插入数据 if(p == NULL) return false; LNode *s; s = (LNode*)malloc(sizeof(LNode)); s->data = e ; s->next = p->next; p->next = s; return true; } bool ListIndexPriorInsert(LNode *p , ElemType e){ // 指定节点前插入数据 // 用交数据的方法 if(p == NULL) return false; LNode *s; s = (LNode*)malloc(sizeof(LNode)); s->data = e ; s->next = p->next; // 先把节点插入到后面,在交换节点的数据 p->next = s; ElemType temp = p->data; p->data = s->data; s->data = temp; return true; } bool ListDelete(LinkList &L , int index , ElemType &e){// 删除指定位置的节点,并返回系节点的数据 if(index < 1 ) return false; LNode *p = L; int j = 1 ; while(p != NULL && j < index-1){ p = p->next; j++; } if(p == NULL) return false; LNode *q = p->next; e = q->data; p->next = q->next; free(q); return true; } bool ListDeletePoint(LNode *p){/// 删除指定节点 if(p == NULL) return false; /// 这里注意最后一个节点 LNode *q = p->next; p->data = q->data; p->next = q->next; free(q); return true; } LNode *GetElem(LinkList L , int index){/// 查找指定位序的节点 if(index < 1) return NULL; LNode *p = L; int j = 0; while(p!=NULL && j < index-1){ j++; p = p->next; } if(p == NULL) return NULL; return p; } LNode * LocateElem(LinkList L , ElemType e){ // 按值查找 LNode *p = L; while(p != NULL && p->data != e){ p = p->next; } if(p == NULL) return NULL; return p; } int ListLenght(LinkList L){/// 求链表长度 int len = 0; LNode *p = L; while(p != NULL){ len++; p = p->next; } return len; } LinkList List_TailInsert(LinkList &L){ // 尾插法插入数据 // 我们这里是创建链表 , 所以链表L进来都是空的 , 如果不是空链表,用一个while走到最后 LNode *r = L; int x ; printf("请输入数据(输入999表示结束):"); scanf("%d",&x); LNode *s; if(r == NULL){ // 传进来的L有可能是空的,这里要特判, 跟带头节点的不一样的点 s = (LNode*)malloc(sizeof(LNode)); s->data = x ; s->next = NULL; r = s ; L = r; // 把第一个节点的位置记住 ,不然就是返回L,L是空的 ,才进这里啊 scanf("%d" , &x); } while(x != 999){ s = (LNode*)malloc(sizeof(LNode)); s->data = x ; s->next = NULL; // 这里初始化节点的next了,出循环的时候就不用r->next = NULL; r->next = s; r = s; scanf("%d" , &x); } return L; } LinkList List_HeadInsert(LinkList &L){ // 头插法插入数据 LNode *p = L; LNode *s ; int x ; printf("请输入数据(输入888表示结束):"); scanf("%d" , &x); while(x != 888){ s = (LNode*)malloc(sizeof(LNode)); s->data = x ; s->next = p ; p = s ; // 因为这个是不带头节点的,所以这个p节点要一直向前移动,p节点一直指向最前面 scanf("%d" , &x); } L = p; return L; } LinkList fanzhuanList(LinkList &L){ // 逆置链表 LNode *pre = NULL , *r = NULL; while(L!=NULL){ r = L->next; L->next = pre; pre = L; L = r ; } L = pre; return L; } void bianliList(LinkList L){ LNode *p = L; while(p != NULL){ printf("%d " , p->data); p = p->next; } printf("\n"); } int main() { LinkList L = NULL; printf("初始化插入数据:"); for(int i = 1 ; i <= 5 ; i++) ListInsert(L , i , i); bianliList(L); LNode *temp_Node = L; printf("指定第一个节点后插入数据10:\n"); ListIndexNextInsert(temp_Node , 10) ; bianliList(L); temp_Node = L; //printf("ceshi = %d\n" , temp_Node->data); printf("指定第一个节点前插入数据8:\n"); ListIndexPriorInsert(temp_Node , 8); bianliList(L); printf("删除指定位序的节点,并返回元素的值(这里指定的是位序3,也就是元素10):\n"); ElemType e ; ListDelete(L , 3 , e); printf("删除的元素:%d\n" , e); bianliList(L); temp_Node = L; // 指向第一个节点 printf("删除指定的节点(指定第一个节点)\n"); ListDeletePoint(temp_Node); // bianliList(L); printf("查询指定位序的节点(指定3吧)\n"); temp_Node = GetElem(L , 3); if(temp_Node!=NULL){ printf("找到位序为3的节点了,节点元素为:%d\n" , temp_Node->data); } printf("查找指定元素值的节(指定5吧)\n"); temp_Node = LocateElem(L , 5); if(temp_Node!=NULL){ printf("找到值为5的节点了\n"); } printf("链表的长度为:%d\n" , ListLenght(L)); printf("尾插法插入数据(我们重新创建一个新的链表)\n"); LinkList temp_Tail = NULL; temp_Tail = List_TailInsert(temp_Tail); bianliList(temp_Tail); printf("头插法插入数据(我们重新创建一个新的链表)\n"); LinkList temp_Head = NULL; temp_Head = List_HeadInsert(temp_Head); bianliList(temp_Head); printf("\n\n链表逆置\n"); printf("逆置前:"); bianliList(L); fanzhuanList(L); printf("逆置后:"); bianliList(L); return 0; }
原文:https://www.cnblogs.com/Li-ningning/p/14630749.html