[数据结构学习]单链表常用操作

来源:互联网 发布:淘宝好的军品店 编辑:程序博客网 时间:2024/05/20 21:20

想到数据结构和算法的学习就头疼,对于我一个学java的来说,真后悔当初没有好好学了(c、c++的知识基本也快忘光光了),

可是还得硬着头皮学呀(考虑到明年找工作的事儿),就先从单链表下手吧,

想想若是让我这个新手一个一个的写算法去实现,似乎还不太现实。

还是先参考别人的把基础搞清楚,以后再慢慢深入学习比较合适~

参考原文:http://blog.csdn.net/xiajun07061225/article/details/9246573

注:自己只是在此基础上加了 头插法和尾插法建立单链表(带头结点)、单链表插入结点、单链表清空这三个操作。

话不多说,开始单链表的学习->Go

代码如下:

#include <iostream>#include <stack>#include <cstdlib>using namespace std;//单链表节点数据结构定义typedef struct link_node_s{int m_val;struct link_node_s *next;}link_node_t,*link_list_t;//函数:创建单链表(头插法)link_list_t create_linklist(int *a,int n);//函数:创建单链表(头插法,带头结点)link_list_t create_linklist2(int *a,int n);//函数:创建单链表(尾插法,带头结点)link_list_t create_linklist3(int *a,int n);//函数:打印单链表(从头到尾)void print_linklist(link_list_t head);//函数:打印单链表(从头到尾,带头结点)void print_linklist2(link_list_t t);//函数:打印单链表(从尾到头)void print_linklist_reverse(link_list_t head);//函数:新建链表节点link_list_t creart_linknode(int val);//函数:带头结点的单链表插入操作void insert_linklist(link_list_t *t,int i,int val);//函数:清空单链表void empty_linklist(link_list_t *t);//函数:删除链表中的某一个节点(前提条件:该节点一定存在)//性能要求:在O(1)时间复杂度内实现void delete_node_exist(link_list_t *head,link_list_t node_deleted);//函数:删除链表中数据值等于给定值的节点void delete_node(link_list_t *head,int val);//函数:获得链表中的倒数第K个节点link_list_t get_kth_node(link_list_t head,int k);//函数:反转链表link_list_t reverse_linklist(link_list_t head);//函数:合并两个已排序的链表(递归方法实现)link_list_t merge_linklist_recursive(link_list_t head1,link_list_t head2);int main(){const int num1 = 8;const int num2 = 10;int *a = new int[num1];int *b = new int[num2];int *a_sorted = new int[num1];int *b_sorted = new int[num2];    /**********************简单测试********************/    //测试1int *c = new int[num2]{1,6,3,7,9,3,4,5,6,7};link_list_t list3 = create_linklist(c,num2);print_linklist(list3);//因为是头插法,所以会逆序输出,7是头结点    //测试2link_list_t list4 = create_linklist2(c,num2);print_linklist2(list4);    //测试3link_list_t list5 = create_linklist3(c,num2);print_linklist2(list5);    //测试4    insert_linklist(&list5,0,99);print_linklist2(list5);//测试5empty_linklist(&list5);    print_linklist2(list5);    /***************************************************/    //生成创建链表所需数据for(int i = 0;i < num1;++i){*(a + i) = rand() % 100;*(a_sorted + i) = 50 - i * 2 + 8;}for(int i = 0;i < num2;++i){*(b + i) = rand() % 200;*(b_sorted + i) = 50 - i * 4 + 1;}cout << "**********创建链表测试**********" << endl;link_list_t list1 = create_linklist(a,num1);link_list_t list2 = create_linklist(b,num2);link_list_t list_sorted1 = create_linklist(a_sorted,num1);link_list_t list_sorted2 = create_linklist(b_sorted,num2);cout << "**********输出链表测试(正向输出)**********" << endl;cout << "链表1:" << endl;print_linklist(list1);    cout << "链表2:" << endl;print_linklist(list2);cout << "链表1(已序):" << endl;print_linklist(list_sorted1);cout << "链表2(已序):" << endl;print_linklist(list_sorted2);cout << "**********输出链表测试(逆向输出)**********" << endl;print_linklist_reverse(list1);cout << "**********获取链表的倒数第K个节点测试**********" << endl;int k = 3;link_list_t kth_node = get_kth_node(list1,k);if(NULL == kth_node)cout << "链表中倒数第" << k << "个节点不存在" << endl;elsecout << "链表中倒数第" << k <<"个节点是: " <<kth_node->m_val << endl;k = 8;kth_node = get_kth_node(list1,k);if(NULL == kth_node)cout << "链表中倒数第" << k << "个节点不存在" << endl;elsecout << "链表中倒数第" << k <<"个节点是: " <<kth_node->m_val << endl;k = 11;kth_node = get_kth_node(list1,k);if(NULL == kth_node)cout << "链表中倒数第" << k << "个节点不存在" << endl;elsecout << "链表中倒数第" << k <<"个节点是: " <<kth_node->m_val << endl;cout << "**********删除链表中一定存在的节点测试(注意传递的是链表的引用)**********" << endl;link_list_t node_deleted = list1;while(node_deleted->m_val != *(a + 4))node_deleted = node_deleted->next;cout << "删除节点" << *(a + 4) << "之后的单链表:" << endl;delete_node_exist(&list1,node_deleted);print_linklist(list1);node_deleted = list1;while(node_deleted->m_val != *(a + 6))node_deleted = node_deleted->next;cout << "删除节点" << *(a + 6) << "之后的单链表:" << endl;delete_node_exist(&list1,node_deleted);print_linklist(list1);cout << "**********删除链表中值等于给定值的节点测试(不一定存在,输入参数是int型值)**********" << endl;const int val_deleted = 22;delete_node(&list1,val_deleted);cout << "删除值等于" << val_deleted << "之后的链表:" << endl;print_linklist(list1);cout << "**********合并链表测试**********" << endl;link_list_t merge_list_head = merge_linklist_recursive(list_sorted1,list_sorted2);print_linklist(merge_list_head);return 0;}//函数:创建单链表(头插法,不带头结点)//a为指向整型数组的指针,n为链表的长度link_list_t create_linklist(int *a,int n){link_list_t head = NULL;if(NULL == a || 0 == n)return NULL;for(int i = 0;i < n;++i){link_list_t new_node = creart_linknode(*(a + i));if(NULL == head){head = new_node;}else{new_node->next = head;head = new_node;}}return head;}//函数:创建单链表(头插法,带头结点)link_list_t create_linklist2(int *a,int n){if(NULL == a || 0 == n)return NULL;    //创建头结点    link_list_t head=new link_node_t;head->next=NULL;for(int i = 0;i < n;++i){link_list_t new_node = creart_linknode(*(a + i));        new_node->next = head->next;//要插入的新结点指向链表的第一个结点        head->next = new_node;}return head;}//函数:创建单链表(尾插法,带头结点)//需要设置一个尾指针rlink_list_t create_linklist3(int *a,int n){if(NULL == a || 0 == n)return NULL;    //创建头结点    link_list_t head=new link_node_t;head->next=NULL;//设置尾指针    link_list_t r=head;for(int i = 0;i < n;++i){link_list_t new_node = creart_linknode(*(a + i));        r->next=new_node;        r=new_node;}return head;}//函数:新建链表节点link_list_t creart_linknode(int val){link_list_t node = new link_node_t;node->m_val = val;node->next = NULL;return node;}//函数:打印单链表void print_linklist(link_list_t head){link_list_t node = head;cout << "正向输出单链表" << endl;while(node != NULL){cout << node->m_val << " ";node = node->next;}cout << endl;return;}//函数:打印单链表(带头结点)void print_linklist2(link_list_t t){t=t->next;cout << "正向输出单链表" << endl;while(t != NULL){cout << t->m_val << " ";t = t->next;}cout << endl;return;}//函数:打印单链表(从尾到头)void print_linklist_reverse(link_list_t head){stack<int> node_stack;//这里定义了一个存放整型元素的栈link_list_t node = head;while(node != NULL){node_stack.push(node->m_val);node = node->next;}cout << "逆向输出单链表" << endl;while(!node_stack.empty()){cout << node_stack.top() << " ";node_stack.pop();}cout << endl;return;}//函数:带头结点的单链表插入操作//前提:插入位置小于表长void insert_linklist(link_list_t *t,int i,int val){//在第i个位置插入结点,该结点数据域为val    link_list_t s=*t;    if(s->next==NULL){        return;    }    int n=0;    while(n<i){        s=s->next;        n++;    }    //此时,t指向第i-1个结点    link_list_t node=new link_node_t;    node->m_val=val;    node->next=s->next;    s->next=node;    return;}//函数:清空单链表void empty_linklist(link_list_t *t){    link_list_t s=*t;    link_list_t u;    while(s->next!=NULL){        u=s->next;        s->next=u->next;        delete u;        u=NULL;    }}//函数:删除链表中的某一个节点(前提条件:该节点一定存在)//性能要求:在O(1)时间复杂度内实现void delete_node_exist(link_list_t *head,link_list_t node_deleted){//注意head参数为指针类型//算法思想://通过拷贝要删除节点的后继节点的内容覆盖要删除节点的内容,然后删除要删除节点的后继节点即可//要考虑的特殊情况是:要删除的节点是链表尾部节点,仍然需要遍历链表if(NULL == head || NULL == node_deleted)return;//要删除的节点不是尾节点if(node_deleted->next != NULL){link_list_t next_node = node_deleted->next;node_deleted->m_val = next_node->m_val;node_deleted->next = next_node->next;delete next_node;//删除节点next_node = NULL;//同时指向NULL;因为delete一个指针之后,只是回收指针指向位置的空间,而指针本身的值不变.你需要手工将其赋值为NULL。}//链表中只有一个节点else if(*head == node_deleted){delete node_deleted;node_deleted = NULL;*head = NULL;}//要删除的节点是尾节点else{link_list_t node = *head;while(node->next != node_deleted)node = node->next;node->next = node_deleted->next;delete node_deleted;node_deleted = NULL;}return;}//函数:删除链表中数据值等于给定值的节点void delete_node(link_list_t *head,int val){if(NULL == head){cout << "Delete node failed :The node to be delete not exist!" << endl;return;}if(val == (*head)->m_val){link_list_t node = *head;*head = (*head)->next;delete node;node=NULL;return;}//首先判断该节点是否存在链表中link_list_t node = *head;while(node->next != NULL){if(val == node->next->m_val)break;node = node->next;}//存在满足条件的节点if(node->next != NULL){link_list_t node_delete = node->next;node->next = node_delete->next;delete node_delete;node_delete=NULL;}elsecout << "删除失败:链表中不存在值等于" << val << "的节点" << endl;return;}//函数:获得链表中的倒数第K个节点link_list_t get_kth_node(link_list_t head,int k){//性能:只需遍历链表一遍即可//算法思想:设置两个指针,一个指向链表头部,一个指向第k个节点,然后两个指针同时向后移动,当第二个指针指向链表的尾节点时,第一个指针指向的节点便是倒数第K个节点//注意代码的鲁棒性,防止程序的崩溃if(NULL == head || k <= 0)return NULL;//设置两个指针link_list_t p1 = head,p2 = head;int i = 0;//第二个指针向前走k-1步while(i < k - 1 && p2->next != NULL){p2 = p2->next;++i;}//注意链表中总节点数小于K的情况if(i != k - 1 && NULL == p2->next)return NULL;//两个指针同时向后前进while(p2->next != NULL){p1 = p1->next;p2 = p2->next;}return p1;}//函数:反转链表//返回值:反转之后的链表头节点link_list_t reverse_linklist(link_list_t head){//链表为空或者只有一个节点if(NULL == head || NULL == head->next)return head;link_list_t prev_node = NULL,next_node,cur_node = head,head_reverse;while(cur_node != NULL){next_node = cur_node->next;if(NULL == next_node)head_reverse = cur_node;//原链表尾节点即逆转后链表的头节点cur_node->next = prev_node;prev_node = cur_node;cur_node = next_node;}return head_reverse;}//函数:合并两个已排序的链表(递归方法实现)link_list_t merge_linklist_recursive(link_list_t head1,link_list_t head2){if(NULL == head1)return head2;else if(NULL == head2)return head1;link_list_t merge_head = NULL;if(head1->m_val < head2->m_val){merge_head = head1;merge_head->next = merge_linklist_recursive(head1->next,head2);}else{merge_head = head2;merge_head->next = merge_linklist_recursive(head1,head2->next);}return merge_head;}


原创粉丝点击