单链表总结


个人总结,以及借鉴他人代码,有些代码来自平时积累,不记得出处,请见谅。

欢迎各位转载,希望对大家有用!如有错误欢迎指正,谢谢!

struct node {
	int val;
	node *next;
};




//链表翻转
static void Reverse(struct node* headRef) {
	struct node* result = NULL;//首节点为空
	struct node* current = headRef;
	struct node* next;
	while (current != NULL) {

		next = current->next; // tricky: note the next node--》先得到下一个节点
		current->next = result; // move the node onto the result》指向上一节点
		result = current;
		current = next;

	}
	headRef = result;
}


//递归翻转

//利用递归的性质,先遍历,最后倒序改变!

void RecursiveReverse(struct node* headRef) {
	struct node* first;
	struct node* rest;
	if (headRef == NULL) return; // empty list base case
	first = headRef; // suppose first = {1, 2, 3}
	rest = first->next; //         rest = {2, 3}
	if (rest == NULL) return; // empty rest base case

	RecursiveReverse(&rest); // Recursively reverse the smaller {2, 3} case
	// after: rest = {3, 2}

	first->next->next = first; // put the first elem on the end of the list
	first->next = NULL; // (tricky step -- make a drawing)//末尾加入NULL
	headRef = rest; // fix the head pointer//传递给头节点,每个都是关乎自身
}


//求长度

int Length(struct node* head) {
	int count = 0;
	struct node* current = head;
	while (current != NULL) {
		count++;
		current=current->next;
	}
	return(count);
}

//加入节点在头前

void Push(struct node* headRef, int newData) {
	struct node* newNode =
		(struct node*) malloc(sizeof(struct node)); // allocate node
	newNode->data = newData; // put in the data
	newNode->next = (headRef); // link the old list off the new node
	(headRef) = newNode; // move the head to point to the new node
}




struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};


//合并俩个链表并排序

ListNode *sort_merge(ListNode *first_lk,ListNode *second_lk) {   

	ListNode head_temp(0);  
	ListNode* temp_head = &head_temp;   

	ListNode *save_head=temp_head;  
	ListNode* head ;  

	while(first_lk!=NULL&&second_lk!=NULL)  
	{  
		if(first_lk->val<second_lk->val)  
		{  
			temp_head->next=first_lk;  
			first_lk=first_lk->next;  
		}  
		else  
		{  
			temp_head->next=second_lk;  
			second_lk=second_lk->next;     
		}  
		temp_head=temp_head->next;  
	}  
	if(first_lk != NULL)  
		temp_head->next=first_lk;  
	else  
		temp_head->next=second_lk;  

	head=save_head->next;  
	return head;  
}  


//获取链表的中间位置    --》通过快慢俩指针,一个一次走一步snow,一个一次走俩步fast
// len/2 下整
ListNode *get_midpos(ListNode *head,ListNode *end) {  

	ListNode *mid_pos,*pre_pos;  
	ListNode *end_pos;  

	//if(head == NULL||head->next==NULL)return head;  

	mid_pos=head;  
	end_pos=head;  

	while(end_pos != end&&end_pos->next != end)  
	{  
		pre_pos=mid_pos;  //用于去下整
		mid_pos=mid_pos->next;  

		end_pos=end_pos->next->next;  
	}  
	return pre_pos;  
}  


//基于以上函数,进行归并排序实现时间复杂度为O(nlgn)的链表排序!

ListNode * merge_sort(ListNode *head) {   

	ListNode *mid_pos,*mid_next_llk;  
	ListNode *sort_list_1,*sort_list_2;  

	if(head == NULL||head->next==NULL)return head;//为空或者为单独一个节点  

	mid_pos=get_midpos(head,NULL);  

	mid_next_llk=mid_pos->next;//第二个链表位置  
	mid_pos->next=NULL;//拆分成俩个链表   

	sort_list_1=merge_sort(head);  

	sort_list_2=merge_sort(mid_next_llk);  //注意这个对链表操作是有修改的!特别是头指针位置!

	return   merge(sort_list_1,sort_list_2);//合并  


}  //详细见:http://blog.csdn.net/jiangxi756/article/details/16839901


//从中间撕裂链表

void spilt_mid(ListNode *src,ListNode *first,ListNode *second)
{
	
	ListNode *mid_pos=get_midpos(src,NULL);
	
	second=mid_pos->next;//链表2
	
	mid_pos=NULL;
	first=src;//链表1

}




//删除有序列表的重复串

// Remove duplicates from a sorted list
void RemoveDuplicates(struct node* head) {
	struct node* current = head;26
		if (current == NULL) return; // do nothing if the list is empty
	// Compare current node with next node
	while(current->next!=NULL) {
		if (current->data == current->next->data) {
			struct node* nextNext = current->next->next;
			free(current->next);
			current->next = nextNext;
		}
		else {
			current = current->next; // only advance if no deletion
		}
	}
}

//添加节点到尾部

void Append(struct node* aRef, struct node* bRef) {
	struct node* current;
	if (aRef == NULL) { // Special case if a is empty
		aRef = bRef;
	}
	else { // Otherwise, find the end of a, and append b there
		current = aRef;
		while (current->next != NULL) { // find the last node
			current = current->next;
		}24
			current->next = bRef; // hang the b list off the last node
	}
	bRef=NULL; // NULL the original b, since it has been appended above
}



//插入排序


//以下用于有序链表插入一个元素
// Uses special case code for the head end
void SortedInsert(struct node* headRef, struct node* newNode) 
{
	// Special case for the head end
	if (headRef == NULL || (headRef)->data >= newNode->data) //比头结点大
	{
		newNode->next = headRef;
		headRef = newNode;
	}
	else {
		// Locate the node before the point of insertion-->定位节点插入位置
		struct node* current = headRef;
		while (current->next!=NULL && current->next->data<newNode->data) 
		{
			current = current->next;
		}

		newNode->next = current->next;
		current->next = newNode;//以上俩句用于插入!
	}
}


void InsertSort(struct node* headRef) {
	struct node* result = NULL; // build the answer here
	struct node* current = headRef; // iterate over the original list
	struct node* next;
	while (current!=NULL) {
		next = current->next; // tricky - note the next pointer before we change it
		SortedInsert(result, current);
		current = next;
	}
	headRef = result;
}


//pop实现

int Pop(struct node* headRef) {
	struct node* head;
	int result;
	head = headRef;
	assert(head != NULL);
	result = head->data; // pull out the data before the node is deleted
	headRef = head->next; // unlink the head node for the caller
	// Note the * -- uses a reference-pointer
	//  just like Push() and DeleteList().
	free(head); // free the head node
	return(result); // don't forget to return the data from the link
}

//删除链表-》用临时指针暂存,再删!
void DeleteList(struct node* headRef) {
	struct node* current = headRef; // deref headRef to get the real head
	struct node* next;
	while (current != NULL) {
		next = current->next; // note the next pointer
		free(current); // delete the node
		current = next; // advance to the next node
	}
	headRef = NULL; // Again, deref headRef to affect the real head back
	// in the caller.
}


//从下标为0,开始,逐个比较判断
int GetNth(struct node* head, int index) {
	struct node* current = head;
	int count = 0; // the index of the node we're currently looking at
	while (current != NULL) {
		if (count == index) return(current->data);
		count++;
		current = current->next;
	}
	assert(0); // if we get to this line, the caller was asking
	// for a non-existent element so we assert fail.
}

//给单链表建环---找到指定交点,在调整指针

bool build_loop_list(node *head ,int index)//从0开始下标
{
	int count = 0;
	int *ptemp_node_start,*ptemp_node_end;	
	while(count<index)
	{
		if(head==NULL)return false;
		head=head->next;
		count++;

	}
	ptemp_node_start = head;

	while(head->next!=NULL)//求环末尾节点
	{
		head=head->next;
	}
	
	ptemp_node_end = head;

	ptemp_node_end->next=ptemp_node_start;

	return true;

}

//检测单链表是否有环

bool detect_looplink(node *head)  
{  
	node *quick_node = head->next, *slow_node = head;  

	if(head == NULL || head->next == NULL)  
	{  
		return false;  
	}  

	while(quick_node != slow_node)  
	{  
		if(quick_node == NULL || slow_node == NULL)  
			break;  
		quick_node = quick_node->next->next;  
		slow_node = slow_node->next;  
	}  
	if(quick_node != NULL && slow_node != NULL)    //非尾节点相遇   
		return true; 

	return false;  
}  

//检测两条链表是否相交,并找到相应交点--
//思路:把2个链表各遍历一遍,记下长度length1和length2,若2者的尾节点指针相等,则相交。   
// 之后再把长的链表从abs(len1-len2)的位置开始遍历,第一个相等的指针为目标节点

node* detect_intersect_links(node *first_link, node *second_link)  
{  
	int legnth1 = 1, length2 = 1, pos = 0;  
	node *cur = NULL, *longer_link = first_link, *shorter_link = second_link;  
	if(first_link == NULL || second_link == NULL)  
	{  
		return NULL;  
	}  
	while(first_link->next || second_link->next)     //遍历2个链表   
	{  
		if(first_link->next)  
		{  
			first_link = first_link->next;  
			++legnth1;  
		}  
		if(second_link->next)  
		{  
			second_link = second_link->next;  
			++length2;  
		}  
	}  
	if(first_link != second_link)                 //比较尾节点   
	{  
		return NULL;  
	}  
	pos = legnth1 - length2;  
	if(legnth1 < length2)                  //保证 longer_link为长链表   
	{  
		pos = length2 - legnth1;  
		cur = longer_link;  
		longer_link = shorter_link;  
		shorter_link = cur;  
	}  
	while(pos-- > 0)  
		longer_link = longer_link->next;//长链表先定位到多余长度的下一个节点  
	while(longer_link || shorter_link)  
	{  
		if(longer_link == shorter_link)                  //找到第一个交点   
		{  
			return longer_link;  
		}  
		longer_link = longer_link->next;  
		shorter_link = shorter_link->next;  
	}  
	return NULL;  
}  




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值