链表的基础操作总结(链表创建,插入,删除,遍历等等)
直接上代码吧,感觉注释还可以,应该可以看的懂。。不懂的话。。
就再看看吧。。。
// 数据结构基础--链表的创建及链表基本操作 #include <stdio.h> #include <malloc.h> #include <stdlib.h> typedef struct Node { int data ; // 数据域 struct Node * pNext ; // 指针域 }NODE, *PNODE ; // NODE 等价于struct Node, PNODE等价于struct Node* /**********************************/ // 调用函数声明 /**********************************/ PNODE creat_list(void) ; // 创建链表 void traverse_list(PNODE phead) ; // 遍历输出链表 bool is_empty(PNODE pHead) ; // 判断链表是否为空 int length_list(PNODE pHead) ; // 求链表长度 bool insert_list(PNODE pHead, int pos, int val) ; // 插入链表元素 bool delete_list(PNODE pHead, int pos, int *) ; // 删除链表元素 void sort_list(PNODE pHead) ; // 对链表进行排序 /**********************************/ // 主函数 /**********************************/ int main() { PNODE pHead = NULL ; // 等价于struct Node* pHead = NULL ; int val, pos, ele ; pHead = creat_list() ; // creat_list(), 创建一个非循环链表 if (is_empty(pHead)) { printf("链表为空!长度为0 。\n") ; } else { printf("链表不为空!其长度为%d。\n\n", length_list(pHead)) ; printf("您所创建的链表是:\n") ; traverse_list(pHead) ; // 遍历该链表 printf("\n") ; } printf("对该链表从大到小排序后为:\n") ; sort_list(pHead) ; traverse_list(pHead) ; printf("\n您是否要对该链表插入元素:(y/n) \n") ; char ch; printf("Please enter:") ; getchar() ; scanf("%c" , &ch) ; printf("%c\n", ch) ; if (ch == 89 || ch == 121) { printf("输入您要插入的元素及位置(以逗号隔开):") ; scanf("%d,%d", &pos, &ele) ; insert_list(pHead, pos, ele) ; printf("插入元素后该链表为:\n") ; traverse_list(pHead) ; } else { printf("您选择不插入数据!") ; } printf("\n请输入您要删除的元素位置:\n") ; scanf("%d", &pos) ; if (delete_list(pHead, pos, &val)) { printf("删除成功,您删除的元素是%d。\n", val) ; printf("删除后的链表为:\n") ; traverse_list(pHead) ; } return 0 ; } /**********************************/ // 创建链表调用函数 /**********************************/ PNODE creat_list(void) // 该函数为PNODE类型的,即是其返回值PNODE类型的,即是一个地址 { int len ; // 用来存放有效节点的初始个数 int i ; int val ; // 用来临时存放用户输入的节点的值 PNODE pHead = (PNODE) malloc(sizeof(NODE)) ; // 分配内存空间,创建链表 if ( pHead == NULL) { printf("内存分配失败,程序将终止!\n") ; exit(-1) ; } PNODE pTail = pHead ; pTail ->pNext = NULL ; printf("请输入您要生成的链表节点数:len=") ; scanf("%d" , &len) ; for (i = 0; i<len; ++ i) { printf("请输入第%d个节点值:", i+1) ; scanf("%d", &val) ; printf("\n") ; PNODE pNew = (PNODE) malloc(sizeof(NODE)) ; // 增加节点,分配内存 if ( NULL == pNew) { printf("内存分配失败,程序将终止!\n") ; exit(-1) ; } pNew ->data = val ; // pTail ->pNext = pNew ; pNew ->pNext = NULL ; pTail = pNew ; } return pHead ; } /**********************************/ // 遍历链表调用函数 /**********************************/ void traverse_list(PNODE phead) { PNODE p = phead->pNext ; while (p != NULL) { printf("%d\t", p->data) ; p = p->pNext ; } printf("\n") ; } /**********************************/ // 判断链表是否为空调用函数 /**********************************/ bool is_empty(PNODE pHead) { if ( pHead->pNext == NULL) // 头结点指针域为空,则链表为空 { return true ; } else { return false ; } } /**********************************/ // 求链表长度调用函数 /**********************************/ int length_list(PNODE pHead) { int len = 0 ; PNODE p = pHead ->pNext ; while ( p != NULL) { ++ len ; p = p->pNext ; } return len ; } /**********************************/ // 对链表排序调用函数--从大到小 /**********************************/ void sort_list(PNODE pHead) { int i, j , t; int len = length_list(pHead) ; PNODE p, q ; // 类似于数组的冒泡排序--完全同质 for (i =0, p = pHead->pNext; i<len-1; ++i, p = p->pNext) { for (j =i+1, q = p->pNext; j<len ; ++j, q = q->pNext) { if (p->data < q->data) { t = p->data ; p->data = q->data ; q->data = t ; } } } return ; } /**********************************/ // 对链表插入元素调用函数 /**********************************/ /* 插入元素的原理: if you want to insert an element to this 链表。The first thing you have to do is 把这个要插入的位置腾出来。 即是必须创建一个新的链表元素,而且是自由的链表元素---等待安排。 并且有一个新的链表指针,指向(如何使其指向亦是一个值得思考的问题)要插入的位置的前面---监视该位置,留待后用。 然后,用你所创建那个自由的链表元素插入。 插入的前提是将目标链表截成两端--从要插入的位置前面截断,最后用挂靠的方式链接即可。 其原理是---p->next 所代表的是一个地址,也可以认为是下一个链表元素 关于自由链表元素--其data域用于存储要插入的元素值。 此时还需要创建一个临时的链表元素,用于临时存储地址。 具体如下: pNew -> data = val ; // 自由元素数据域 PNODE q = p->next ; // 临时元素存储pos位置的地址 p->next = pNew ; // 将自由元素的地址赋值给监视元素的地址域--挂到监视元素后面 pNew->next = q ; // 将临时元素--即是原来pos位置元素 的地址赋值给自由元素--挂到自由元素后面 此时就完成整个链接--将插入的元素挂到其前面的那个元素后面,再将原来后半部分的元素挂到新插入的元素后面 */ bool insert_list(PNODE pHead, int pos, int val) { int i = 0 ; PNODE p = pHead ; while(p != NULL && i<pos-1) { p = p->pNext ; ++i ; } if (i>pos-1 || p==NULL) { return false ; } PNODE pNew = (PNODE)malloc(sizeof(NODE)) ; if (pNew == NULL) { printf("动态内存分配失败!") ; exit(-1) ; } pNew -> data = val ; // 自由元素数据域 PNODE q = p->pNext ; // 临时元素存储pos位置的地址 p->pNext = pNew ; // 将自由元素的地址赋值给监视元素的地址域--挂到监视元素后面 pNew->pNext = q ; // 将临时元素--即是原来pos位置元素的地址赋值给自由元素--挂到自由元素后面 // 此时完成链表的重新链接 return true ; } /**********************************/ // 对链表删除元素调用函数 /**********************************/ bool delete_list(PNODE pHead, int pos, int *val) { int i = 0 ; PNODE p = pHead ; while(p->pNext != NULL && i<pos-1) { p = p->pNext ; ++i ; } if (i>pos-1 || p->pNext==NULL) { return false ; } PNODE q = p->pNext ; *val = q->data ; p->pNext = p->pNext->pNext ; free(q) ; // 释放内存!!! q=NULL ; return true ; }