单链表总结
typedef struct ListNode{
int val;
ListNode *next;
ListNode(int x): val(x), next(NULL){}
} ListNode;
/*
*@brief: 打印单链表
*/
void printSList(const ListNode *head){
const ListNode *ptr = head;
while(ptr){
cout << ptr->val << " ";
ptr = ptr->next;
}
cout << endl;
}
/*
*@brief:用给出的数组以头插法创建单链表
*/
void createSList(ListNode *&head, int a[], int n){
head = NULL;
for(int i = 0; i < n; i++){
ListNode *node = new ListNode(a[i]);
node->next = head;
head = node;
}
}
/* 1
*@brief:单链表逆序
*/
void reverseList(ListNode *&head){
if(NULL == head) return; //注意点一
ListNode *ptr, *qptr;
ptr = head;
head = NULL;
while(ptr){
qptr = ptr;
ptr = ptr->next; //标记下当前结点,然后移动指针
qptr->next = head;
head = qptr;
}
}
/* 2
*@brief: 在单链表中查找倒数第k个元素
*/
ListNode* findKthFromEnd(ListNode *head, int k){
if(NULL == head || 0 == k) return NULL; //注意点一
ListNode *ptr = head;
int count = 0;
while(ptr && count != k){
count++;
ptr = ptr->next;
}
if(count < k) return NULL; //注意点二
ListNode *qptr = head;
while(ptr){
qptr = qptr->next;
ptr = ptr->next;
}
return qptr;
}
/* 3
*@brief: 找出链表的中间元素
*/
const ListNode *findMidElement(const ListNode *head){
if(head == NULL) return NULL;
const ListNode *oneStep = head;
const ListNode *twoStep = head;
while(twoStep->next){
if(oneStep){ oneStep = oneStep->next; }
if(twoStep){
twoStep = twoStep->next;
if(NULL == twoStep) break; //注意点一
}
if(twoStep){
twoStep = twoStep->next;
if(NULL == twoStep) break; //注意点二
}
}
return oneStep;
}
/* 4
*@brief: 在单链表中删除值为x的结点 该结点不为最末尾的结点如果为最末尾结点要从头遍历一遍进行删除
*/
void deleteNodeInList(ListNode *&head, int x){
if(head == NULL) return;
ListNode *ptr = head->next;
ListNode *prePtr = head;
if(head->val == x){ //头指针的情况特殊处理
ptr = head;
head = head->next;
delete ptr;
return;
}
while(ptr){
if(ptr->val == x) {
prePtr->next = ptr->next;
delete ptr;
break;
}
prePtr = ptr; //记录前一个结点
ptr = ptr->next;
}
}
/* 5
*@brief: 将两个不交叉的有序列合并成一个有序序列 用一的头结点作最终的头结点
*/
void combineTwoOrderLists(ListNode *&head1, ListNode *head2){
ListNode *newHead = NULL;
ListNode *tailList = NULL;
ListNode *ptr;
if(NULL == head1){
head1 = head2;
return;
}
if(head1 && head2){
if(head1->val < head2->val){
ptr = head1;
head1 = head1->next;
}else{
ptr = head2;
head2 = head2->next;
}//新的头结点
newHead = ptr;
tailList = newHead;
newHead->next = NULL;
}
while(head1 && head2){
if(head1->val < head2->val){
ptr = head1;
head1 = head1->next;
}else{
ptr = head2;
head2 = head2->next;
}
ptr->next = NULL;
tailList->next = ptr;
tailList = tailList->next;
}
if(head1){ tailList->next = head1; }
if(head2){ tailList->next = head2; }
head1 = newHead;
}
/* 6
* @brief: 交换单链表任意两个元素
* @param: head头指针,k第k个元素第 x第x个元素
* @return: 返回尾指针
*/
void swapKthAndXthElem(ListNode *head, int k, int x){
if(NULL == head || k <= 0 || x <= 0) return;
ListNode *firstNode, *secondNode;
ListNode *ptr = head;
k--; x--; //注意点一
while(ptr && k && x){
k--; x--;
ptr = ptr->next;
}
firstNode = ptr; //找出第一个结
while(ptr && k){ ptr = ptr->next; k--; }
while(ptr && x){ ptr = ptr->next; x--; }
if(k || x) return; //如果链表没有那么元素直接返回
secondNode = ptr;//找出第二个结点
swap(firstNode->val, secondNode->val);
}
/* 7
*@brief: 检测链表是否有环,如果链表有环,一个指针移动一步,另一个移动两步肯定有相交的情况
*/
bool checkCircle4List(ListNode *head){
ListNode *oneStep, *twoStep;
if(NULL == head) return false;
oneStep = twoStep = head;
do {
oneStep = oneStep->next;
twoStep = twoStep->next;
if(NULL == twoStep) return false; //注意点一
twoStep = twoStep->next;
} while (oneStep != twoStep);
return true;
}
/* 8
*@brief:判断两个单链表是否相交
*/
bool isTwoListsJoin(ListNode *head1, ListNode *head2){
if(NULL == head1 || NULL == head2) return false;
int m = 0, n = 0;
ListNode *ptr;
ptr = head1;
//计算链表一的长度
while(ptr){ m++; ptr = ptr->next;}
//计算链表二的长度
ptr = head2; while(ptr){ n++; ptr = ptr->next;}
int tmpLen; //判断两个链表哪个更长
if(m > n){
tmpLen = m - n;
while(tmpLen){
tmpLen--; head1 = head1->next;
}
}else{
tmpLen = n - m;
while(tmpLen){
tmpLen--; head2 = head2->next;
}
}
//找出交点
while(head1 && head2){
//如果是计算两个单链表的相交点可以返回其指针
if(head1 == head2) return true;
head1 = head1->next;
head2 = head2->next;
}
return false;
}
/* 9-1
* @brief: 模拟快速排序的链表排序算法 一次分割
* @param: head头指针,end尾指针,第一次end为NULL
* @return: 返回尾指针
*/
ListNode* partation(ListNode *head, ListNode *end){
if(head == NULL) return NULL;
ListNode *iptr = head; //j = left
ListNode *jptr = head->next; // i = left + 1
while(jptr != end){
if(jptr->val < iptr->val){
iptr = iptr->next; //i++
swap(jptr->val, iptr->val);
}
jptr = jptr->next; //j++
}
swap(head->val, iptr->val); //交换left与i
return iptr;
}
/* 9-2
*@brief: 链表排序 如果元素重复太多算法会退化为n2 n的平方时间复杂度
*@param: head头指针,end尾指针,第一次end为NULL
*/
void sortList(ListNode *head, ListNode *end){
if(head != end){
ListNode *pos = partation(head, end);
sortList(head, pos);
sortList(pos->next, NULL);
}
}
/* 10
*@brief: 删除单链表中相同的元素,前提相同元素相邻
*如果不相邻可以考虑用map或set(最好),或相排序再处理,如果元素范围固定可以考虑使用hash table
*/
void uniqueList(ListNode *head){
if(NULL == head) return;
ListNode *ptr, *qptr;
ptr = head;
while(ptr->next){
if(ptr->val != ptr->next->val){
ptr = ptr->next;
}else{
qptr = ptr->next;
ptr->next = ptr->next->next;
delete qptr;
}
}
}