include<iostream>
using namespace std;
//單鏈表
typedef struct Lnode{
int data;
struct Lnode *next;
}Lnode;
//雙鏈表
typedef struct DLnode{
int data;
struct DLnode *next;
}DLnode;
/*
尾插法建立單鏈表
*/
Lnode * Create(Lnode *head, int *a, int n){
Lnode *first, *node;
first = (Lnode *)malloc(sizeof(Lnode)); //頭結點
head = first;
first->next = NULL;
for (int i = 0; i < n; ++i){
node = (Lnode *)malloc(sizeof(Lnode));
node->data = *(a + i);
first->next = node;
first = first->next;
}
first->next = NULL;
return head;
}
/*
頭插法建立單鏈表
*/
Lnode * HeadCreate(Lnode *head, int *a, int n){
Lnode *first, *node;
first = (Lnode *)malloc(sizeof(Lnode)); //頭結點
head = first;
first->next = NULL;
for (int i = 0; i < n; ++i){
node = (Lnode *)malloc(sizeof(Lnode));
node->data = *(a + i);
node->next = first->next;
first->next = node;
}
return head;
}
/*
在指定位置插入節點val
*/
Lnode * Insert(Lnode * head, int n, int val){
Lnode *p = head;
Lnode node = (Lnode)malloc(sizeof(Lnode));
for (int i = 0; i < n - 1; ++i){
p = p->next;
}
node->data = val;
node->next = p->next;
p->next = node;
return head;
}
/*
刪除 data 為val的某個節點
*/
int Del(Lnode *head, int val){
Lnode*p, *q;
p = head; //傳入頭指針,然后p保存頭指針信息,修改p,即等同于修改head頭指針
while (p->next != NULL){ //p指向刪除節點的前一個節點
if (p->next->data == val)
{
break;
}
p = p->next;
}
if (p->next == NULL){
return 0;
}
else{
q = p->next;
p->next = q->next;
free(q);
return 1;
}
}
/*
單鏈表反轉
*/
Lnode* Reverse(Lnode *head){
Lnode *first = head->next, *tmp;
head->next = NULL;
while (first != NULL)
{
tmp = first->next;
first->next = head->next;
head->next = first;
first = tmp;
}
return head;
}
/*
- 構建有環單鏈表
*/
Lnode *CirLnode(Lnode *head, int num) {
Lnode *tmp, *tail;
tmp = tail = head->next;
for (int i = 1; i < num; ++i) {
tmp = tmp->next;
}
while (tail->next != NULL) {
tail = tail->next;
}
tail->next = tmp;
return head;
}
/*
- 判斷單鏈表是否有環
*/
int IsCir(Lnode *head) {
Lnode *first, *last;
first = head;
last = head;
while (last != NULL && last->next != NULL) {
last = last->next->next;
first = first->next;
if (first == last) {
cout << first->data << endl; //在環中相遇的點,不一定是環的初始點
//求環的初始點
first = head;
while (first->next!=NULL){ //first和last在環中相遇的時候,使first指針回到head節點,last不動,然后first和last都每次走一步,兩者再次相遇的點就是環的初始節點
first = first->next;
last = last->next;
if (first == last){
cout << "初始環點" << first->data << endl;
break;
}
}
return 1;
}
}
return 0;
}
/*
約瑟夫環問題
*/
int JoseCircle(Lnode *head,int num){
Lnode p = head,tmp,*q;
int i = 1;
q = p->next;
while (p!=q){
i++;
p = q;
q = q->next;
if (i == num){
tmp = q;
p->next = tmp->next;
q = p->next;
free(tmp);
i = 1;
}
}
return q->data;
}
/*
查找單鏈表中的倒數第K個結點(k > 0)
*/
int FindLast(Lnode * head, int k){
Lnode *p, *q;
q = head;
p = q->next;
for (int i = 0; i < k; ++i){ //使用兩個指針,前面的指針走到正K,后面的指向第一個,兩者相差為k-1,然后同時走,直到前面走到最后,后指針的位置即為所求
q = q->next;
}
if (q == NULL){ //k大于鏈表個數
return -1;
}
while (q->next != NULL){
p = p->next;
q = q->next;
}
/*
while(p){
p=p->next;
i++;
if(i>k) q=q->next; //p先走,只有存在p走過了K個節點,q才開始走,當p走到終點,q指向倒數K個節點
}
if(q==head) return 0; //q要么指向頭結點,要么指向倒數第K個
else cout<<q->data<<endl;
*/
return p->data;
}
/*
- 刪除相同節點
*/
Lnode *DelSame(Lnode *head) {
Lnode *p, *q, *tmp;
p = head->next;
while (p != NULL) {
q = p;
while (q->next != NULL) {
if (q->next->data == p->data) {
tmp = q->next;
q->next = tmp->next;
free(tmp);
}
else{
q = q->next;
}
}
p = p->next;
}
return head;
}
/*
查找單鏈表的中間節點
*/
int FindMid(Lnode *head){
Lnode *p, *q;
p = q = head->next;
while (q->next != NULL){
if (q->next->next != NULL){
p = p->next;
q = q->next->next;
}
else{
break;
}
}
return p->data;
}
/*
統計節點的個數
*/
int CalcNum(Lnode *head){
int n = 0;
Lnode *tmp = head;
if (head->next == NULL){
return n;
}
else{
while (tmp->next != NULL){
n++;
tmp = tmp->next;
}
return n;
}
}
/*
- 合并兩個有序鏈表
*/
Lnode *MergeLnode(Lnode *h1, Lnode *h2) {
Lnode *p1, *p2, *p3, *q;
p1 = h1->next, p2 = h2->next;
q = p3 = h1;
q->next = NULL;
while (p1 != NULL && p2 != NULL) {
if (p1->data <= p2->data) {
q->next = p1;
p1 = p1->next;
}
else {
q->next = p2;
p2 = p2->next;
}
q = q->next;
}
if (p1 != NULL) q->next = p1;
if (p2 != NULL) q->next = p2;
return p3;
}
/*
- 求A,B鏈表的差集A-B
*/
Lnode *Diff(Lnode *h1, Lnode *h2) {
Lnode *p = h1, *q = h2;
Lnode *tmp;
while (p->next != NULL && q->next != NULL) {
if (p->next->data < q->next->data) {
p = p->next;
}
else if (p->next->data > q->next->data) {
q = q->next;
}
else {
tmp = p->next;
p->next = tmp->next;
free(tmp);
}
}
return h1;
}
/*
求A,B鏈表的交集
*/
void Common(Lnode *h1, Lnode *h2){
Lnode *p = h1, *q = h2;
while (p->next != NULL && q->next != NULL) {
if (p->next->data < q->next->data) {
p = p->next;
}
else if (p->next->data > q->next->data) {
q = q->next;
}
else {
cout << p->next->data << " ";
p = p->next;
q = q->next;
}
}
cout << endl;
}
/*
刪除單鏈表中的最小值節點
*/
Lnode *DelMin(Lnode *head){
Lnode *q = head->next, min = q,tmp=head;
while (q != NULL && q->next!=NULL){
if (q->next->data < min->data){
tmp = q;
min = q->next;
}
q = q->next;
}
tmp->next = min->next;
free(min);
return head;
}
/*
將A鏈表拆分成A,B,其中A是data為奇數的點,B是data為偶數的點,順序不變
*/
Lnode * SplitLink(Lnode *h1, Lnode *h2){
Lnode p = h1,t ;
Lnode *q = (Lnode *)malloc(sizeof(Lnode));
h2 = q;
q->next = NULL;
while (p->next != NULL){
if (p->next->data % 2 == 0){ //如果是偶數,就取出 放到B中,否則就繼續前進,然后A就剩余奇數
t = p->next;
p->next = t->next;
t->next = NULL;
q->next = t;
q = q->next;
}
else{
p = p->next;
}
}
return h2;
}
/*
按照val值將單鏈表分成左右部分,左邊比它小,右邊比它大
*/
Lnode * Partation(Lnode *head,int val){
Lnode *p = head;
Lnode *small, *equal, *big; //將單鏈表拆成三個鏈表, 分別定義三個頭指針,
small = equal = big = NULL;
Lnode * smallA, *equalA, *bigA ; //三個鏈表的尾指針
smallA = equalA = bigA = NULL;
while (p->next!=NULL){
if (p->next->data < val){
if (small == NULL){ //初始時,頭尾指針均指向第一個進入大,等,小的節點
smallA = small = p->next;
}
else{
smallA->next = p->next; //不是第一個節點的時候,采用尾插法將節點插入鏈表
smallA = smallA->next;
}
}
else if (p->next->data == val){
if (equal == NULL){
equalA = equal = p->next;
}
else{
equalA->next = p->next;
equalA = equalA->next;
}
}
else {
if (big == NULL){
bigA = big = p->next;
}
else{
bigA->next = p->next;
bigA = bigA->next;
}
}
p = p->next;
}
if (small!=NULL && equalA != NULL) { //當小鏈表不為空,且等鏈表不為空,鏈接兩個鏈表,等鏈表后置為空
equalA->next = NULL;
smallA->next = equal;
}
if (equalA!=NULL && bigA != NULL) { // 同理鏈接等鏈表和大鏈表
bigA->next = NULL;
equalA->next = big;
}
head->next = small != NULL ? small : equal != NULL ? equal : big;
return head;
}
/*
正序打印單鏈表
*/
void show(Lnode * head){
while (head->next != NULL){
cout << head->next->data << " ";
head = head->next;
}
cout << endl;
}
/*
逆序打印單鏈表
*/
void ShowTail(Lnode *head) { //print from tail,顛倒順序的問題,采用棧,并且去掉頭結點
Lnode *p = head;
if (p == NULL) {
return;
}
ShowTail(p->next);
cout << p->data << " ";
}
void tt(int *p){
int a = 3;
int *q = p;
q = &a;
}
void test(Lnode *head){ //一個單鏈表,first指針在前,last指針在后,first置空后,last便訪問不到first后的節點
//last置空后,并不妨礙first訪問后面的節點
Lnode *p = head->next;
Lnode *q = p;
p = p->next->next;
p->next = NULL;
q = q->next;
cout << p->data << endl;
}
void main(){
int a[] = {2,1,3,5,4};
int b[] = { 3,4, 5, 6, 7, 8 };
int lenA = sizeof(a) / sizeof(a[0]);
int lenB = sizeof(b) / sizeof(b[0]);
Lnode *head = NULL, *tail = NULL , *h2=NULL; //頭指針
head = Create(head, a, lenA); //指針作為函數參數時,傳遞的也是指針的地址拷貝,所以指正不會改變,傳入堆指針時,指針的值才會變化
show(head);
tail = HeadCreate(tail, b, lenB);
Reverse(tail);
show(tail);
/*
cout << "節點個數為: " << CalcNum(head) << endl;
*tail = Reverse(tail);
show(tail);
if (Del(head, 4) > 0){
cout << "找到并刪除" << endl;
show(head);
}
Insert(head, 3, 6);
show(head);
cout << "節點個數為: " << CalcNum(head) << endl;
cout << FindMid(head) << endl;
head = DelMin(head);
show(head);
h2=SplitLink(head, h2);
show(head);
show(h2);
int *p = (int *)malloc(sizeof(int));
tt(p);
if (p == NULL){
cout << "null" << endl;
}
else{
cout << " not null" << endl;
}
*/
//head = CirLnode(head, 1);
/*if (IsCir(head)){
cout << "has a circle " << endl;
}
else{
cout << "no circle " << endl;
}*/
//cout << "Last out " << JoseCircle(head, 3) << endl;
//Common(head, tail);
head = Partation(head, 2);
show(head);
free(head);
free(tail);
system("pause");
}