我面试遇到的C语言中单链表相关的操作粗浅实现
2015-05-16 12:43
471 查看
主要包括单链表中节点的插入, 删除, 反转链表, 链表排序, 查询链表中第几个或倒数第几个节点的值(即将补充的有链表是否有环, 两个链表是否相交以及第一个公共节点). 仅用于备注, 不断更新, 代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct _LinkedNodeTAG { char value; struct _LinkedNodeTAG *next; } LinkedNode; LinkedNode *new_LinkedNode(char value) { LinkedNode *pNode; pNode = (LinkedNode *)malloc(sizeof(LinkedNode)); pNode->value = value; return pNode; } LinkedNode *new_LinkedNode_ex(char value, LinkedNode *next) { LinkedNode *pNode; pNode = (LinkedNode *)malloc(sizeof(LinkedNode)); pNode->value = value; pNode->next = next; return pNode; } void iter_print(LinkedNode *head) { while (head) { printf("%c ", head->value); head = head->next; } printf("\n"); } /* 获取链表上索引位置为index的节点, 需要考虑到链表头节点是否为NULL, 链表是否只有一个节点, 索引是否大于链表的长度. * 这里设定索引从0开始, 索引为正将从头节点向前搜索, 如果为负表示倒数第index个节点, 比如-1表示倒数第一个, 即尾节点. * 求倒数第n个节点的值的思路是使用两个指针从头结点开始一起遍历, 保证指针间隔为n, 第一个指针遍历完时, 后面的指针正好指在倒数第n个节点上 */ LinkedNode *get_node_at(LinkedNode *head, int index) { if (index >= 0) {/* -0也是0 */ while (index-- > 0 && head) {/* 两个出口, 抵达索引位置或者链表已遍历完(索引位置还未到达) */ head = head->next; } return head; } else { index = -index; LinkedNode *node = head; /* 这里其实可以只用一个循环, 但是每次循环都做判断 */ while (index-- > 0 && head) { head = head->next; } if (index > 0) return NULL; while (head) { head = head->next; node = node->next; } return node; } } int remove_node(LinkedNode *head, LinkedNode *node) { if (!head || !node) return -1; if (head == node && !head->next) {/* 既是头节点又没有下一个节点, 即只有一个节点 */ free(head); head = NULL; return 0; } if (head != node && !node->next) {/* 有多个节点, 要删除的可能是尾节点的情况 */ while (head && head->next != node) head = head->next; if (!head) {/* node可能不在链表上 */ return -1; } else if (head->next == node) {/* 此时head即为倒数第二个节点 */ head->next = NULL; free(node); node = NULL; } return 0; } /* 有多个节点, 且要删除的不是尾节点的情况, 如果node在另一个链表上, 责任留给调用者. 这里思路是: * 将要删除的节点node的下一个元素的内容value拷贝到要node上, 将node的next指向原下一个元素的next指向的节点, 然后删除原下一个元素节点 */ LinkedNode *next = node->next; node->value = next->value; node->next = next->next; free(next); next = NULL; return 0; } /* 一个链表, 在node节点前插入inserting节点 */ int insert_node_before(LinkedNode *head, LinkedNode *node, LinkedNode *inserting) { if (!head || !node || !inserting) return -1; if (head == node) { inserting->next = head; /* 链表head节点发生改变 */ return 0; } /* 有多个节点, 如果node在另一个链表上, 责任留给调用者. 这里思路是: * 交换node和inserting的内容value, 使原node变成inserting, inserting变成node, 然后node的next原指向的节点由inserting指向, node的next指向inserting */ char temp_value = node->value; node->value = inserting->value; inserting->value = temp_value; inserting->next = node->next; node->next = inserting; return 0; } /* 首先不断递归进去, 到倒数第二个节点后, 通过next的next, 向前指向前一个节点, 并去掉指向后一个节点但指针 */ LinkedNode *reverse_recusive(LinkedNode *head) { if (!head || !head->next) return head; LinkedNode *newHead = reverse_recusive(head->next); head->next->next = head; head->next = NULL; return newHead; } LinkedNode *reverse_loop(LinkedNode *head) { if (!head) return head; LinkedNode *prev, *next, *remember; /* 使用三个指针 */ prev = head; next = head->next; prev->next = NULL; /* 第一个作为尾节点, 置空其next指针 */ while(next) { remember = next->next; /* 记住下一个的下一个, 以防将下一个但next指向自己以后链表断掉 */ next->next = prev; /* 反转 */ /* 向前移动指针 */ prev = next; next = remember; } return prev; } /* 选定一个pivot, 这里是begin, 使用两个指针, big指针往前走, 如果发现指向的值比pivot小, 则向前移动small指针一步, 并交换这两个指针指向的节点内容value. * 这样, small左边到pivot所有节点的内容比pivot指向的节点内容小, 而big左边到small所有节点的内容比pivot指向的节点内容大, 符合了快速排序中一种partition实现思路. * 遍历一遍链表后把pivot指向的节点内容与small指针交换, 保证此时的pivot前面的比它小, 后面的比它大. */ LinkedNode *partition(LinkedNode *begin, LinkedNode *end, LinkedNode *pivot) { LinkedNode *small, *big; if (!begin || !pivot) { return NULL; } small = big = begin; while(big != end) { if (big->value < pivot->value) { small = small->next; char temp = big->value; big->value = small->value; small->value = temp; } big = big->next; } char temp = pivot->value; pivot->value = small->value; small->value = temp; return small; } void quick_sort(LinkedNode *begin, LinkedNode *end) { if (begin != end) { LinkedNode * pivot = partition(begin, end, begin); quick_sort(begin, pivot); quick_sort(pivot->next, end); } } int main(void) { LinkedNode *head; LinkedNode *a = new_LinkedNode('e'); LinkedNode *b = new_LinkedNode('f'); LinkedNode *c = new_LinkedNode('b'); LinkedNode *d = new_LinkedNode('a'); LinkedNode *e = new_LinkedNode('d'); LinkedNode *f = new_LinkedNode('g'); LinkedNode *g = new_LinkedNode('c'); a->next = b; b->next = c; c->next = d; d->next = e; e->next = f; f->next = g; g->next = NULL; head = a; iter_print(head); //LinkedNode *node = new_LinkedNode('m'); //insert_node_before(head, c, node); //iter_print(head); //remove_node(head, d); //iter_print(head); //head = reverse_recusive(head); //iter_print(head); //head = reverse_loop(head); //iter_print(head); //partition(head, head, NULL, head); //iter_print(head); //quick_sort(head, NULL); //iter_print(head); //LinkedNode *t = get_node_at(head, -5); //if (!t) { // printf("NULL\n"); //} else { // printf("%c\n", t->value); //} }
相关文章推荐
- 单链表相关操作之C语言实现:插入,删除,倒转,复制,查找。。。
- c语言实现链表的相关的操作
- C语言实现链表插入,删除相关操作
- C语言实现单链表相关操作
- 【数据结构】链表及相关操作(C语言实现)
- C语言实现链表的相关操作
- 【C语言】指针、链表的原理和各类操作相关心得以及学生信息管理系统的改写报告
- C:C语言实现的链表及其各种链表操作
- C语言来实现链表的相加基本操作 桂林电子科技大学 大二实验
- C语言单向链表的实现与操作
- 单链表及其基本操作(C语言实现)
- 单链表的基本操作(C语言实现)
- [原]C语言实现双向链表删除节点、插入节点、双向输出等操作
- C语言实现双向链表删除节点、插入节点、双向输出等操作
- c语言实现单链表数据结构及其基本操作
- 链表基础操作+实例[C语言实现]
- c语言实现链表及其基本操作
- 单链表相关操作--C语言实现
- C语言实现单向链表的常见操作
- !-- 基于静态数组的顺序表相关操作C语言实现 --!