commit
cc189078e3
95
c-cpp/05_array/array.c
Normal file
95
c-cpp/05_array/array.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
struct array {
|
||||||
|
int size;
|
||||||
|
int used;
|
||||||
|
int *arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
void dump(struct array *array)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < array->used; idx++)
|
||||||
|
printf("[%02d]: %08d\n", idx, array->arr[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void alloc(struct array *array)
|
||||||
|
{
|
||||||
|
array->arr = (int *)malloc(array->size * sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
int insert(struct array *array, int elem)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
if (array->used >= array->size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (idx = 0; idx < array->used; idx++) {
|
||||||
|
if (array->arr[idx] > elem)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < array->used)
|
||||||
|
memmove(&array->arr[array->used], &array->arr[idx],
|
||||||
|
(array->used - idx) * sizeof(int));
|
||||||
|
|
||||||
|
array->arr[idx] = elem;
|
||||||
|
array->used++;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int delete(struct array *array, int idx)
|
||||||
|
{
|
||||||
|
if (idx < 0 || idx >= array->used)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memmove(&array->arr[idx], &array->arr[idx+1],
|
||||||
|
(array->used - idx) * sizeof(int));
|
||||||
|
array->used--;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int search(struct array *array, int elem)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < array->used; idx++) {
|
||||||
|
if (array->arr[idx] == elem)
|
||||||
|
return idx;
|
||||||
|
if (array->arr[idx] > elem)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
struct array ten_int = {10, 0, NULL};
|
||||||
|
|
||||||
|
alloc(&ten_int);
|
||||||
|
if (!ten_int.arr)
|
||||||
|
return -1;
|
||||||
|
insert(&ten_int, 1);
|
||||||
|
insert(&ten_int, 3);
|
||||||
|
insert(&ten_int, 2);
|
||||||
|
printf("=== insert 1, 3, 2\n");
|
||||||
|
dump(&ten_int);
|
||||||
|
|
||||||
|
idx = search(&ten_int, 2);
|
||||||
|
printf("2 is at position %d\n", idx);
|
||||||
|
idx = search(&ten_int, 9);
|
||||||
|
printf("9 is at position %d\n", idx);
|
||||||
|
|
||||||
|
printf("=== delete [6] element \n");
|
||||||
|
delete(&ten_int, 6);
|
||||||
|
dump(&ten_int);
|
||||||
|
printf("=== delete [0] element \n");
|
||||||
|
delete(&ten_int, 0);
|
||||||
|
dump(&ten_int);
|
||||||
|
return 0;
|
||||||
|
}
|
148
c-cpp/06_linkedlist/list_isPalindrome/LinkList.cpp
Normal file
148
c-cpp/06_linkedlist/list_isPalindrome/LinkList.cpp
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#include "LinkList.h"
|
||||||
|
|
||||||
|
void CreateListHead(LinkList *&L,ElemType a[],int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
LinkList *s;
|
||||||
|
L = (LinkList *)malloc(sizeof(LinkList));
|
||||||
|
L->next = NULL;
|
||||||
|
for(i = 0;i < n;i++)
|
||||||
|
{
|
||||||
|
s=(LinkList*)malloc(sizeof(LinkList));
|
||||||
|
s->data = a[i];
|
||||||
|
s->next = L->next;
|
||||||
|
L->next = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void CreateListTail(LinkList *&L,ElemType a[],int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
LinkList * s,* r;
|
||||||
|
L = (LinkList *)malloc(sizeof(LinkList));
|
||||||
|
r = L;
|
||||||
|
for(i = 0;i < n;i++)
|
||||||
|
{
|
||||||
|
s = (LinkList *)malloc(sizeof(LinkList));
|
||||||
|
s->data = a[i];
|
||||||
|
r->next = s;
|
||||||
|
r = s;
|
||||||
|
}
|
||||||
|
r->next = NULL;
|
||||||
|
}
|
||||||
|
void InitList(LinkList *&L)
|
||||||
|
{
|
||||||
|
L=(LinkList *)malloc(sizeof(LinkList));
|
||||||
|
L->next = NULL;
|
||||||
|
}
|
||||||
|
void DestroyList(LinkList *&L)
|
||||||
|
{
|
||||||
|
LinkList * pre = L,*p = L->next;
|
||||||
|
while(p!=NULL)
|
||||||
|
{
|
||||||
|
free(pre);
|
||||||
|
pre = p;
|
||||||
|
p = L->next;
|
||||||
|
}
|
||||||
|
free(pre);
|
||||||
|
}
|
||||||
|
bool ListEmpty(LinkList *L)
|
||||||
|
{
|
||||||
|
return(L->next==NULL);
|
||||||
|
}
|
||||||
|
int ListLength(LinkList *L)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
LinkList * p = L;
|
||||||
|
while(p->next!=NULL)
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
p=p->next;
|
||||||
|
}
|
||||||
|
return(n);
|
||||||
|
}
|
||||||
|
void ShowList(LinkList *L)
|
||||||
|
{
|
||||||
|
LinkList * p = L->next;//Ö¸Ïò¿ªÊ¼½Úµã
|
||||||
|
while(p!=NULL)
|
||||||
|
{
|
||||||
|
printf(" %c ",p->data);
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
bool GetListElem(LinkList *L,int i,ElemType &e)
|
||||||
|
{
|
||||||
|
int j = 0;
|
||||||
|
LinkList *p = L;
|
||||||
|
while(j<i&&p!=NULL)
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
p=p->next;
|
||||||
|
}
|
||||||
|
if(p==NULL)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e=p->data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int LocateElem(LinkList*L,ElemType e)
|
||||||
|
{
|
||||||
|
int i=1;
|
||||||
|
LinkList *p = L->next;
|
||||||
|
while(p!=NULL&&p->data!=e){
|
||||||
|
p=p->next;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if(p==NULL)
|
||||||
|
{
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return(i);
|
||||||
|
}
|
||||||
|
bool ListInsert(LinkList *&L,int i,ElemType e)
|
||||||
|
{
|
||||||
|
int j=0;
|
||||||
|
LinkList *p =L,*s;
|
||||||
|
while(j<i-1&&p!=NULL)
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
p=p->next;
|
||||||
|
}
|
||||||
|
if(p==NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s= (LinkList*)malloc(sizeof(LinkList));
|
||||||
|
s->data = e;
|
||||||
|
s->next = p->next;
|
||||||
|
p->next = s;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool ListDelete(LinkList *&L,int i,ElemType &e)
|
||||||
|
{
|
||||||
|
int j=0;
|
||||||
|
LinkList * p =L,*q;
|
||||||
|
while(j<i-1&&p!=NULL)
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
p=p->next;
|
||||||
|
}
|
||||||
|
if(p==NULL)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
q=p->next;
|
||||||
|
if(q==NULL)
|
||||||
|
return false;
|
||||||
|
e=q->data;
|
||||||
|
p->next=q->next;
|
||||||
|
free(q);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
24
c-cpp/06_linkedlist/list_isPalindrome/LinkList.h
Normal file
24
c-cpp/06_linkedlist/list_isPalindrome/LinkList.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef LINKLIST_H
|
||||||
|
#define LINKLIST_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
typedef char ElemType;
|
||||||
|
typedef struct LNode
|
||||||
|
{
|
||||||
|
ElemType data;
|
||||||
|
struct LNode*next;
|
||||||
|
}LinkList;
|
||||||
|
|
||||||
|
void CreateListHead(LinkList *&L,ElemType a[],int n);
|
||||||
|
void CreateListTail(LinkList *&L,ElemType a[],int n);
|
||||||
|
void InitList(LinkList *&L);
|
||||||
|
void DestroyList(LinkList *&L);
|
||||||
|
bool ListEmpty(LinkList *L);
|
||||||
|
int ListLength(LinkList *L);
|
||||||
|
void ShowList(LinkList *L);
|
||||||
|
bool GetListElem(LinkList *L,int i,ElemType &e);
|
||||||
|
int LocateElem(LinkList*L,ElemType e);
|
||||||
|
bool ListInsert(LinkList *&L,int i,ElemType e);
|
||||||
|
bool ListDelete(LinkList *&L,int i,ElemType &e);
|
||||||
|
#endif
|
40
c-cpp/06_linkedlist/list_isPalindrome/main.cpp
Normal file
40
c-cpp/06_linkedlist/list_isPalindrome/main.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include"LinkList.h"
|
||||||
|
char array1[]= {'a','b','c','b','a'};
|
||||||
|
bool isPalindrome(LinkList * list,int length);
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
LinkList * list;
|
||||||
|
|
||||||
|
int length = sizeof(array1)/sizeof(array1[0]);
|
||||||
|
InitList(list);
|
||||||
|
CreateListTail(list,array1,length);//用尾插法创建一个单链表
|
||||||
|
if(isPalindrome(list,length))
|
||||||
|
printf("isPalindrome\n");
|
||||||
|
else
|
||||||
|
printf("isNotPalindrome\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool isPalindrome(LinkList * list,int length)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char buff1[length],buff2[length];
|
||||||
|
ElemType e;
|
||||||
|
for(i=1; i<=length; i++)
|
||||||
|
{
|
||||||
|
GetListElem(list,i,e);//遍历获取链表元素并放入数组中
|
||||||
|
buff1[i-1]=e;//正向数组
|
||||||
|
buff2[length-i]=e;//反向数组
|
||||||
|
}
|
||||||
|
i=0;
|
||||||
|
while(i<=length) {
|
||||||
|
if(buff1[i]==buff2[i])//比较
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
176
c-cpp/06_linkedlist/single_list.c
Normal file
176
c-cpp/06_linkedlist/single_list.c
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct single_list {
|
||||||
|
struct single_list *next;
|
||||||
|
int val;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct single_list_head {
|
||||||
|
struct single_list *head;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool is_empty(struct single_list_head *head)
|
||||||
|
{
|
||||||
|
return head->head == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump(struct single_list_head *head)
|
||||||
|
{
|
||||||
|
struct single_list *tmp = head->head;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
while (tmp) {
|
||||||
|
printf("[%02d]: %08d\n", idx++, tmp->val);
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(struct single_list **prev, struct single_list *elem)
|
||||||
|
{
|
||||||
|
if (!prev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (*prev)
|
||||||
|
elem->next = *prev;
|
||||||
|
*prev = elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert_head(struct single_list_head *head, struct single_list *elem)
|
||||||
|
{
|
||||||
|
insert(&head->head, elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct single_list* delete(struct single_list **prev)
|
||||||
|
{
|
||||||
|
struct single_list *tmp;
|
||||||
|
|
||||||
|
if (!prev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
tmp = *prev;
|
||||||
|
*prev = (*prev)->next;
|
||||||
|
tmp->next = NULL;
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct single_list* delete_head(struct single_list_head* head)
|
||||||
|
{
|
||||||
|
return delete(&head->head);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct single_list** search(struct single_list_head* head, int target)
|
||||||
|
{
|
||||||
|
struct single_list **prev, *tmp;
|
||||||
|
|
||||||
|
for (prev = &head->head, tmp = *prev;
|
||||||
|
tmp && (tmp->val < target);
|
||||||
|
prev = &tmp->next, tmp = *prev)
|
||||||
|
;
|
||||||
|
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverse(struct single_list_head* head)
|
||||||
|
{
|
||||||
|
struct single_list_head tmp;
|
||||||
|
struct single_list *elem;
|
||||||
|
|
||||||
|
while (!is_empty(head)) {
|
||||||
|
elem = delete_head(head);
|
||||||
|
insert_head(&tmp, elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
head->head = tmp.head;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_cyclic(struct single_list_head* head)
|
||||||
|
{
|
||||||
|
struct single_list *s1, *s2;
|
||||||
|
|
||||||
|
s1 = s2 = head->head;
|
||||||
|
|
||||||
|
while(s1 && s2) {
|
||||||
|
s1 = s1->next;
|
||||||
|
s2 = s2->next ? s2->next->next:s2->next;
|
||||||
|
|
||||||
|
if (s1 == s2)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct single_list* middle(struct single_list_head* head)
|
||||||
|
{
|
||||||
|
struct single_list *s1, *s2;
|
||||||
|
struct single_list pseudo_head;
|
||||||
|
|
||||||
|
pseudo_head.next = head->head;
|
||||||
|
s1 = s2 = &pseudo_head;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!s2 || !s2->next)
|
||||||
|
return s1;
|
||||||
|
s1 = s1->next;
|
||||||
|
s2 = s2->next->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
struct single_list_head head = {NULL};
|
||||||
|
struct single_list lists[10];
|
||||||
|
struct single_list **prev;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < 10; idx++) {
|
||||||
|
lists[idx].val = idx;
|
||||||
|
lists[idx].next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_head(&head, &lists[6]);
|
||||||
|
insert_head(&head, &lists[5]);
|
||||||
|
insert_head(&head, &lists[4]);
|
||||||
|
insert_head(&head, &lists[1]);
|
||||||
|
insert_head(&head, &lists[0]);
|
||||||
|
|
||||||
|
printf("=== insert 0, 1, 4, 5, 6\n");
|
||||||
|
dump(&head);
|
||||||
|
|
||||||
|
prev = search(&head, 2);
|
||||||
|
insert(prev, &lists[2]);
|
||||||
|
printf("=== insert 2\n");
|
||||||
|
dump(&head);
|
||||||
|
|
||||||
|
printf("middle elem is %d\n", middle(&head)->val);
|
||||||
|
|
||||||
|
prev = search(&head, 2);
|
||||||
|
if ((*prev) && ((*prev)->val == 2))
|
||||||
|
printf("The list contains 2\n");
|
||||||
|
else
|
||||||
|
printf("The list not contains 2\n");
|
||||||
|
|
||||||
|
delete(prev);
|
||||||
|
prev = search(&head, 2);
|
||||||
|
printf("After remove 2\n");
|
||||||
|
if ((*prev) && ((*prev)->val == 2))
|
||||||
|
printf("The list contains 2\n");
|
||||||
|
else
|
||||||
|
printf("The list not contains 2\n");
|
||||||
|
dump(&head);
|
||||||
|
|
||||||
|
printf("After reverse \n");
|
||||||
|
reverse(&head);
|
||||||
|
dump(&head);
|
||||||
|
|
||||||
|
printf("middle elem is %d\n", middle(&head)->val);
|
||||||
|
|
||||||
|
lists[0].next = &lists[6];
|
||||||
|
printf("list is%s cyclic\n", is_cyclic(&head)?"":" not");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
94
javascript/06_linkedlist/SinglyLinkedList.js
Normal file
94
javascript/06_linkedlist/SinglyLinkedList.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* 1)单链表的插入、删除、查找操作;
|
||||||
|
* 2)链表中存储的是int类型的数据;
|
||||||
|
*/
|
||||||
|
class Node {
|
||||||
|
constructor (element) {
|
||||||
|
this.element = element
|
||||||
|
this.next = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LinkedList {
|
||||||
|
constructor () {
|
||||||
|
this.head = new Node('head')
|
||||||
|
}
|
||||||
|
// 根据value查找节点
|
||||||
|
findByValue (item) {
|
||||||
|
let currentNode = this.head
|
||||||
|
while (currentNode !== null && currentNode.element !== item) {
|
||||||
|
currentNode = currentNode.next
|
||||||
|
}
|
||||||
|
console.log(currentNode)
|
||||||
|
return currentNode === null ? -1 : currentNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据index查找节点
|
||||||
|
findByIndex (index) {
|
||||||
|
let currentNode = this.head
|
||||||
|
let pos = 0
|
||||||
|
while (currentNode !== null && pos !== index) {
|
||||||
|
currentNode = currentNode.next
|
||||||
|
pos++
|
||||||
|
}
|
||||||
|
console.log(currentNode)
|
||||||
|
return currentNode === null ? -1 : currentNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 指定元素向后插入
|
||||||
|
insert (newElement, element) {
|
||||||
|
const currentNode = this.findByValue(element)
|
||||||
|
if (currentNode === -1) {
|
||||||
|
console.log('未找到插入位置')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newNode = new Node(newElement)
|
||||||
|
newNode.next = currentNode.next
|
||||||
|
currentNode.next = newNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找前一个
|
||||||
|
findPrev (item) {
|
||||||
|
let currentNode = this.head
|
||||||
|
while (currentNode.next !== null && currentNode.next.element !== item) {
|
||||||
|
currentNode = currentNode.next
|
||||||
|
}
|
||||||
|
if (currentNode.next === null) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return currentNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据值删除
|
||||||
|
remove (item) {
|
||||||
|
const desNode = this.findByValue(item)
|
||||||
|
if (desNode === -1) {
|
||||||
|
console.log('未找到元素')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const prevNode = this.findPrev(item)
|
||||||
|
prevNode.next = desNode.next
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历显示所有节点
|
||||||
|
display () {
|
||||||
|
let currentNode = this.head
|
||||||
|
while (currentNode !== null) {
|
||||||
|
console.log(currentNode.element)
|
||||||
|
currentNode = currentNode.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test
|
||||||
|
const LList = new LinkedList()
|
||||||
|
LList.insert('chen', 'head')
|
||||||
|
LList.insert('curry', 'chen')
|
||||||
|
LList.insert('sang', 'head')
|
||||||
|
LList.insert('zhao', 'head')
|
||||||
|
console.log('-------------remove item------------')
|
||||||
|
LList.remove('curry', 'chen')
|
||||||
|
LList.display()
|
||||||
|
console.log('-------------find by item------------')
|
||||||
|
LList.findByValue('chen')
|
||||||
|
console.log('-------------find by index------------')
|
||||||
|
LList.findByIndex(2)
|
221
javascript/07_linkedlist/LinkedListAlgo.js
Normal file
221
javascript/07_linkedlist/LinkedListAlgo.js
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
/**
|
||||||
|
* 1) 单链表反转
|
||||||
|
* 2) 链表中环的检测
|
||||||
|
* 3) 两个有序的链表合并
|
||||||
|
* 4) 删除链表倒数第n个结点
|
||||||
|
* 5) 求链表的中间结点
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Node {
|
||||||
|
constructor(element) {
|
||||||
|
this.element = element
|
||||||
|
this.next = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LinkedList {
|
||||||
|
constructor() {
|
||||||
|
this.head = new Node('head')
|
||||||
|
}
|
||||||
|
// 根据value查找节点
|
||||||
|
findByValue(item) {
|
||||||
|
let currentNode = this.head
|
||||||
|
while (currentNode !== null && currentNode.element !== item) {
|
||||||
|
currentNode = currentNode.next
|
||||||
|
}
|
||||||
|
return currentNode === null ? -1 : currentNode
|
||||||
|
}
|
||||||
|
// 根据index查找节点
|
||||||
|
findByIndex(index) {
|
||||||
|
let currentNode = this.head
|
||||||
|
let pos = 0
|
||||||
|
while (currentNode !== null && pos !== index) {
|
||||||
|
currentNode = currentNode.next
|
||||||
|
pos++
|
||||||
|
}
|
||||||
|
return currentNode === null ? -1 : pos
|
||||||
|
}
|
||||||
|
// 指定元素向后插入
|
||||||
|
insert(newElement, element) {
|
||||||
|
const currentNode = this.findByValue(element)
|
||||||
|
if (currentNode === -1) {
|
||||||
|
console.log('未找到插入位置')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newNode = new Node(newElement)
|
||||||
|
newNode.next = currentNode.next
|
||||||
|
currentNode.next = newNode
|
||||||
|
}
|
||||||
|
// 查找前一个
|
||||||
|
findPrev(item) {
|
||||||
|
let currentNode = this.head
|
||||||
|
while (currentNode.next !== null && currentNode.next.element !== item) {
|
||||||
|
currentNode = currentNode.next
|
||||||
|
}
|
||||||
|
if (currentNode.next === null) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return currentNode
|
||||||
|
}
|
||||||
|
// 根据值删除
|
||||||
|
remove(item) {
|
||||||
|
const desNode = this.findByValue(item)
|
||||||
|
if (desNode === -1) {
|
||||||
|
console.log('未找到元素')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const prevNode = this.findPrev(item)
|
||||||
|
prevNode.next = desNode.next
|
||||||
|
}
|
||||||
|
// 遍历显示所有节点
|
||||||
|
display() {
|
||||||
|
let currentNode = this.head
|
||||||
|
while (currentNode !== null) {
|
||||||
|
console.log(currentNode.element)
|
||||||
|
currentNode = currentNode.next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尾插法 反转单链表
|
||||||
|
reverseList() {
|
||||||
|
const root = new Node('head')
|
||||||
|
let currentNode = this.head.next
|
||||||
|
while (currentNode !== null) {
|
||||||
|
const next = currentNode.next
|
||||||
|
currentNode.next = root.next
|
||||||
|
root.next = currentNode
|
||||||
|
currentNode = next
|
||||||
|
}
|
||||||
|
this.head = root
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自己一开始瞎想的。差距啊
|
||||||
|
reverseList2() {
|
||||||
|
let currentNode = this.head.next
|
||||||
|
let reverseList = new LinkedList()
|
||||||
|
const tempArr = []
|
||||||
|
if (currentNode === null || currentNode.next === null) {
|
||||||
|
console.log('节点数小于3,不反转')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
while (currentNode !== null) {
|
||||||
|
tempArr.push(currentNode)
|
||||||
|
currentNode = currentNode.next
|
||||||
|
}
|
||||||
|
for (let i = tempArr.length - 1; i >= 0; i--) {
|
||||||
|
const key = i === tempArr.length - 1 ? 'head' : tempArr[i + 1].element
|
||||||
|
reverseList.insert(tempArr[i].element, key)
|
||||||
|
}
|
||||||
|
reverseList.display()
|
||||||
|
return reverseList
|
||||||
|
}
|
||||||
|
// 环验证
|
||||||
|
checkCircle() {
|
||||||
|
let fast = this.head.next
|
||||||
|
let slow = this.head
|
||||||
|
while (fast !== null && fast.next !== null) {
|
||||||
|
fast = fast.next.next
|
||||||
|
slow = slow.next
|
||||||
|
if (slow === fast) return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 删除倒数第k个节点
|
||||||
|
removeByIndexFromEnd(index) {
|
||||||
|
let pos = 1
|
||||||
|
this.reverseList()
|
||||||
|
let currentNode = this.head.next
|
||||||
|
while (currentNode !== null && pos < index) {
|
||||||
|
currentNode = currentNode.next
|
||||||
|
pos++
|
||||||
|
}
|
||||||
|
if (currentNode === null) {
|
||||||
|
console.log('无法删除最后一个节点或者该节点不存在')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.remove(currentNode.element)
|
||||||
|
this.reverseList()
|
||||||
|
}
|
||||||
|
// 求中间节点
|
||||||
|
findMiddleNode() {
|
||||||
|
let fast = this.head
|
||||||
|
let slow = this.head
|
||||||
|
while (fast.next !== null && fast.next.next !== null) {
|
||||||
|
fast = fast.next.next
|
||||||
|
slow = slow.next
|
||||||
|
}
|
||||||
|
console.log(slow)
|
||||||
|
return slow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const mergeSortedLists = (listA, listB) => {
|
||||||
|
if (!listA) {
|
||||||
|
return listB
|
||||||
|
}
|
||||||
|
if (!listB) {
|
||||||
|
return listA
|
||||||
|
}
|
||||||
|
|
||||||
|
let a = listA
|
||||||
|
let b = listB
|
||||||
|
let resultList = undefined
|
||||||
|
if (a.element < b.element) {
|
||||||
|
resultList = a
|
||||||
|
a = a.next
|
||||||
|
} else {
|
||||||
|
resultList = b
|
||||||
|
b = b.next
|
||||||
|
}
|
||||||
|
let currentNode = resultList
|
||||||
|
while (a !== null && b !== null) {
|
||||||
|
if (a.element < b.element) {
|
||||||
|
currentNode.next = a
|
||||||
|
a = a.next
|
||||||
|
} else {
|
||||||
|
currentNode.next = b
|
||||||
|
b = b.next
|
||||||
|
}
|
||||||
|
currentNode = currentNode.next
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a != null) {
|
||||||
|
currentNode.next = a
|
||||||
|
} else {
|
||||||
|
currentNode.next = b
|
||||||
|
}
|
||||||
|
return resultList
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test
|
||||||
|
const LList = new LinkedList()
|
||||||
|
LList.insert('chen', 'head')
|
||||||
|
LList.insert('curry', 'chen')
|
||||||
|
LList.insert('sang', 'head')
|
||||||
|
LList.insert('zhao', 'head')
|
||||||
|
console.log('-------------start reverse------------')
|
||||||
|
LList.reverseList()
|
||||||
|
LList.display()
|
||||||
|
console.log('-------------check circle------------')
|
||||||
|
console.log(LList.checkCircle())
|
||||||
|
console.log('-------------remove the one before last ------------')
|
||||||
|
LList.removeByIndexFromEnd(2)
|
||||||
|
LList.display()
|
||||||
|
|
||||||
|
const sortedList1 = new LinkedList()
|
||||||
|
sortedList1.insert(9, 'head')
|
||||||
|
sortedList1.insert(8, 'head')
|
||||||
|
sortedList1.insert(7, 'head')
|
||||||
|
sortedList1.insert(6, 'head')
|
||||||
|
const sortedList2 = new LinkedList()
|
||||||
|
sortedList2.insert(21, 'head')
|
||||||
|
sortedList2.insert(20, 'head')
|
||||||
|
sortedList2.insert(19, 'head')
|
||||||
|
sortedList2.insert(18, 'head')
|
||||||
|
console.log('-------------sort two list ------------')
|
||||||
|
let sortedList = mergeSortedLists(sortedList1.head.next, sortedList2.head.next)
|
||||||
|
while (sortedList !== null) {
|
||||||
|
console.log(sortedList.element)
|
||||||
|
sortedList = sortedList.next
|
||||||
|
}
|
139
python/06_linkedlist/singly_linked_list.py
Normal file
139
python/06_linkedlist/singly_linked_list.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
"""
|
||||||
|
1) Insertion, deletion and search of singly-linked list;
|
||||||
|
2) Assumes int type for data in list nodes.
|
||||||
|
|
||||||
|
Author: Wenru
|
||||||
|
"""
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class Node:
|
||||||
|
|
||||||
|
def __init__(self, data: int, next=None):
|
||||||
|
self.data = data
|
||||||
|
self._next = next
|
||||||
|
|
||||||
|
|
||||||
|
class SinglyLinkedList:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._head = None
|
||||||
|
|
||||||
|
def find_by_value(self, value: int) -> Optional[Node]:
|
||||||
|
p = self._head
|
||||||
|
while p and p.data != value:
|
||||||
|
p = p._next
|
||||||
|
|
||||||
|
return p
|
||||||
|
|
||||||
|
def find_by_index(self, index: int) -> Optional[Node]:
|
||||||
|
p = self._head
|
||||||
|
position = 0
|
||||||
|
while p and position != index:
|
||||||
|
p = p._next
|
||||||
|
position += 1
|
||||||
|
|
||||||
|
return p
|
||||||
|
|
||||||
|
def insert_value_to_head(self, value: int):
|
||||||
|
new_node = Node(value)
|
||||||
|
self.insert_node_to_head(new_node)
|
||||||
|
|
||||||
|
def insert_node_to_head(self, new_node: Node):
|
||||||
|
if new_node:
|
||||||
|
new_node._next = self._head
|
||||||
|
self._head = new_node
|
||||||
|
|
||||||
|
def insert_value_after(self, node: Node, value: int):
|
||||||
|
new_node = Node(value)
|
||||||
|
self.insert_node_after(node, new_node)
|
||||||
|
|
||||||
|
def insert_node_after(self, node: Node, new_node: Node):
|
||||||
|
if not node or not new_node:
|
||||||
|
return
|
||||||
|
new_node._next = node._next
|
||||||
|
node._next = new_node
|
||||||
|
|
||||||
|
def insert_value_before(self, node: Node, value: int):
|
||||||
|
new_node = Node(value)
|
||||||
|
self.insert_node_before(node, new_node)
|
||||||
|
|
||||||
|
def insert_node_before(self, node: Node, new_node: Node):
|
||||||
|
if not self._head or not node or not new_node:
|
||||||
|
return
|
||||||
|
if self._head == node:
|
||||||
|
self.insert_node_to_head(new_node)
|
||||||
|
return
|
||||||
|
current = self._head
|
||||||
|
while current._next and current._next != node:
|
||||||
|
current = current._next
|
||||||
|
if not current._next: # node is not even in the list
|
||||||
|
return
|
||||||
|
new_node._next = node
|
||||||
|
current._next = new_node
|
||||||
|
|
||||||
|
def delete_by_node(self, node: Node):
|
||||||
|
if not self._head or not node:
|
||||||
|
return
|
||||||
|
if node._next:
|
||||||
|
node.data = node._next.data
|
||||||
|
node._next = node._next._next
|
||||||
|
return
|
||||||
|
# node is the last one or not in the list
|
||||||
|
current = self._head
|
||||||
|
while current and current._next != node:
|
||||||
|
current = current._next
|
||||||
|
if not current: # node not in the list
|
||||||
|
return
|
||||||
|
current._next = None
|
||||||
|
|
||||||
|
def delete_by_value(self, value: int):
|
||||||
|
if not self._head or not value:
|
||||||
|
return
|
||||||
|
fake_head = Node(value+1)
|
||||||
|
fake_head._next = self._head
|
||||||
|
prev, current = fake_head, self._head
|
||||||
|
while current:
|
||||||
|
if current.data != value:
|
||||||
|
prev._next = current
|
||||||
|
prev = prev._next
|
||||||
|
current = current._next
|
||||||
|
if prev._next:
|
||||||
|
prev._next = None
|
||||||
|
self._head = fake_head._next # in case head.data == value
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
nums = []
|
||||||
|
current = self._head
|
||||||
|
while current:
|
||||||
|
nums.append(current.data)
|
||||||
|
current = current._next
|
||||||
|
if len(nums) > 0:
|
||||||
|
return "->".join(str(num) for num in nums)
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def print_all(self):
|
||||||
|
current = self._head
|
||||||
|
if current:
|
||||||
|
print(f"{current.data}", end="")
|
||||||
|
current = current._next
|
||||||
|
while current:
|
||||||
|
print(f"->{current.data}", end="")
|
||||||
|
current = current._next
|
||||||
|
print("\n", flush=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
l = SinglyLinkedList()
|
||||||
|
for i in range(15):
|
||||||
|
l.insert_value_to_head(i)
|
||||||
|
node9 = l.find_by_value(9)
|
||||||
|
l.insert_value_before(node9, 20)
|
||||||
|
l.insert_value_before(node9, 16)
|
||||||
|
l.insert_value_before(node9, 16)
|
||||||
|
l.delete_by_value(16)
|
||||||
|
node11 = l.find_by_index(3)
|
||||||
|
l.delete_by_node(node11)
|
||||||
|
l.delete_by_node(l._head)
|
||||||
|
l.delete_by_value(13)
|
||||||
|
print(l)
|
92
python/07_linkedlist/linked_list_algo.py
Normal file
92
python/07_linkedlist/linked_list_algo.py
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
"""
|
||||||
|
1) Reverse singly-linked list
|
||||||
|
2) Detect cycle in a list
|
||||||
|
3) Merge two sorted lists
|
||||||
|
4) Remove nth node from the end
|
||||||
|
5) Find middle node
|
||||||
|
|
||||||
|
Author: Wenru
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
class Node:
|
||||||
|
|
||||||
|
def __init__(self, data: int, next=None):
|
||||||
|
self.data = data
|
||||||
|
self._next = next
|
||||||
|
|
||||||
|
# Reverse singly-linked list
|
||||||
|
# 单链表反转
|
||||||
|
# Note that the input is assumed to be a Node, not a linked list.
|
||||||
|
def reverse(head: Node) -> Optional[Node]:
|
||||||
|
reversed_head = None
|
||||||
|
current = head
|
||||||
|
while current:
|
||||||
|
reversed_head, reversed_head._next, current = current, reversed_head, current._next
|
||||||
|
return reversed_head
|
||||||
|
|
||||||
|
# Detect cycle in a list
|
||||||
|
# 检测环
|
||||||
|
def has_cycle(head: Node) -> bool:
|
||||||
|
slow, fast = head, head
|
||||||
|
while fast and fast._next:
|
||||||
|
slow = slow._next
|
||||||
|
fast = fast._next._next
|
||||||
|
if slow == fast:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Merge two sorted linked list
|
||||||
|
# 有序链表合并
|
||||||
|
def merge_sorted_list(l1: Node, l2: Node) -> Optional[Node]:
|
||||||
|
if l1 and l2:
|
||||||
|
p1, p2 = l1, l2
|
||||||
|
fake_head = Node(None)
|
||||||
|
current = fake_head
|
||||||
|
while p1 and p2:
|
||||||
|
if p1.data <= p2.data:
|
||||||
|
current._next = p1
|
||||||
|
p1 = p1._next
|
||||||
|
else:
|
||||||
|
current._next = p2
|
||||||
|
p2 = p2._next
|
||||||
|
current = current._next
|
||||||
|
current._next = p1 if p1 else p2
|
||||||
|
return fake_head._next
|
||||||
|
return p1 or p2
|
||||||
|
|
||||||
|
# Remove nth node from the end
|
||||||
|
# 删除倒数第n个节点。假设n大于0
|
||||||
|
def remove_nth_from_end(head: Node, n: int) -> Optional[Node]:
|
||||||
|
fast = head
|
||||||
|
count = 0
|
||||||
|
while fast and count < n:
|
||||||
|
fast = fast._next
|
||||||
|
count += 1
|
||||||
|
if not fast and count < n: # not that many nodes
|
||||||
|
return head
|
||||||
|
if not fast and count == n:
|
||||||
|
return head._next
|
||||||
|
|
||||||
|
slow = head
|
||||||
|
while fast._next:
|
||||||
|
fast, slow = fast._next, slow._next
|
||||||
|
slow._next = slow._next._next
|
||||||
|
return head
|
||||||
|
|
||||||
|
def find_middle_node(head: Node) -> Optional[Node]:
|
||||||
|
slow, fast = head, head
|
||||||
|
fast = fast._next if fast else None
|
||||||
|
while fast and fast._next:
|
||||||
|
slow, fast = slow._next, fast._next._next
|
||||||
|
return slow
|
||||||
|
|
||||||
|
def print_all(head: Node):
|
||||||
|
nums = []
|
||||||
|
current = head
|
||||||
|
while current:
|
||||||
|
nums.append(current.data)
|
||||||
|
current = current._next
|
||||||
|
print("->".join(str(num) for num in nums))
|
Loading…
Reference in New Issue
Block a user